I like to know how to initialise the array without the loops like for, foreach or any LINQ.
From the following code, need to find under 2m length cars within .Netframework using console application.
{
ArrayList = CarType new ArrayList();
CarType.Add(new CarList("Ford"));
((CarList)CarType[0]).Cars.Add(new Car("Focus", 2));
((CarList)CarType[0]).Cars.Add(new Car("Fiesta", 1));
CarType.Add(new CarList("Peugeout"));
((CarList)CarType[1]).Cars.Add(new Car("206", 1));
((CarList)CarType[1]).Cars.Add(new Car("407", 2));
RemoveLargeCars(CarType);
}
public static ArrayList RemoveLargeCars (ArrayList CarType)
{
//Array List should be here
return CarType;
}
It has got two classes as follows.
class Car
{
public string name;
public float length;
public Car(string newName, float newLength)
{
this.name = newName;
this.length = newLength;
}
}
Class CarList
{
public string CarType;
public ArrayList Pipes;
public CarList(string newCarType)
{
carType = newCarType;
Cars = new ArrayList();
}
}
Can you please let me know how to solve this.
Thanks in advance.
Use the static Adapter method on ArrayList
CarType = ArrayList.Adapter(CarList);
But that probably uses a loop internally, you can't get away from them, but at least this hides them.
Well, first of all you should use the generic list type List<T> instead of ArrayList, that will make the code simpler. (And best practive recommends properties rather than public fields):
class Car {
public string Name { get; set; }
public float Length { get; set; }
public Car(string newName, float newLength) {
Name = newName;
Length = newLength;
}
}
class CarList {
public string CarType { get; set; }
public List<Car> Cars { get; set; }
public CarList(string newCarType, List<Car> newCars) {
CarType = newCarType;
Cars = newCars;
}
public CarList(string newCarType) : this(newCarType, new List<Car>()) {}
}
Now use a List<CarList>:
List<CarList> CarType = new List<CarList>();
CarList ford = new CarList("Ford");
CarType.Add(ford);
ford.Cars.Add(new Car("Focus", 2));
ford.Cars.Add(new Car("Fiesta", 1));
CarList peugeot = new CarList("Peugeout");
CarType.Add(peugeot);
peugeot.Cars.Add(new Car("206", 1));
peugeot.Cars.Add(new Car("407", 2));
List<CarList> smallCars = RemoveLargeCars(CarType);
You can use extension methods to easily filter out cars based on a condition:
public static List<CarList> RemoveLargeCars(List<CarList> CarType) {
return CarType.Select(
t => new CarList(t.CarType, t.Cars.Where(c => c.Length < 2f).ToList()
) .ToList();
}
Note that the method doesn't change the original list, but creates a new list.
Related
I am new at automapper and it is a very good stuff easy to use, but now I have a problem with it. Trying to convert my derived class to base and it gives me
AutoMapper.AutoMapperMappingException
Missing type map configuration or unsupported mapping.
Mapping types: ClientEventDb -> EventId
Database.ClientEventDb -> EventId
Destination path: ClientEvent
Source value:
Event:Login
Automapper wants to convert ClientEventDb to EventId? I don't understand why. EventId is an enum...
Please help me I have run out of ideas.
Here is the code which I run:
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.Take(1000).ToArray();
}
Mapper.CreateMap<ClientEventDb, ClientEvent>();
Console.WriteLine("hello");
return edbl.Select(edb => Mapper.Map<ClientEvent>(edb)).ToArray();
Here are my classes
[Table("events", Schema = "public")]
public class ClientEventDb : ClientEvent
{
public ClientEventDb(string userName, EventId happening, object userObject = null)
: base(userName, happening, userObject)
{
}
public ClientEventDb()
{
}
}
[ProtoContract]
[Table("events", Schema = "public")]
public class ClientEvent : ClientEventBase
{
[ProtoMember(1)]
[Column("username")]
public string UserName { get; private set; }
[ProtoMember(2)]
[Column("time")]
public DateTime DateTime { get; private set; }
[ProtoMember(3)]
[Key]
[Column("id")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; private set; }
[ProtoMember(4)]
[Column("data")]
public byte[] UserObject { get; set; }
public ClientEvent(string userName,EventId happening, object userObject=null) : base(happening)
{
UserName = userName;
DateTime = DateTime.Now;
//UserObject = null;
if (userObject!=null) throw new NotImplementedException();
}
public ClientEvent()
{
}
protected ClientEvent Clone()
{
return (ClientEvent)MemberwiseClone();
}
}
[ProtoContract]
[ProtoInclude(10, typeof(ClientEvent))]
public class ClientEventBase
{
[Column("eventid")]
[ProtoMember(1)]
public int EventIdValue { get; set; } //must be public because of entity framework
[NotMapped]
public EventId EventId
{
get { return (EventId) EventIdValue; }
set { EventIdValue = (int) value; }
}
public ClientEventBase(EventId eventId)
{
EventId = eventId;
}
public ClientEventBase()
{
}
public override string ToString()
{
return String.Format("Event:{0}",EventId);
}
}
public enum EventId
{
Login = 1,
Logout,
ExitApplication,
}
UPDATE
bugfix: ClientEvent [Key] attribute moved to id property
Solution was this (thx to stuartd):
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.ToArray();
}
Mapper.CreateMap<ClientEventDb, ClientEvent>().ConstructUsing((ClientEventDb src) => new ClientEvent());
return edbl.Select(Mapper.Map<ClientEvent>).ToArray();
AutoMapper is confused as its made to map between similar properties in different classes, you are using it incorrectly - you just need to go from the derived class to the base which does not require AutoMapper. You could use this to do what you need....
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.Take(1000).ToArray();
}
return edbl.Cast<ClientEvent>().ToList();
I'd be looking at why you even feel you need a derived ClientEventDb though - understand we dont have the whole picture here but it seems to do nothing in addition to what the base class already does.
The issue is that ClientEvent has two constructors but you have not told AutoMapper which to use.
If you want it to use your constructor with parameters, change your mapping code to this and it will work:
Mapper.CreateMap<ClientEventDb, ClientEvent>()
.ConstructUsing(src => new ClientEvent(src.UserName, src.EventId));
Or to make AutoMapper use the default constructor:
Mapper.CreateMap<ClientEventDb, ClientEvent>()
.ConstructUsing((ClientEventDb src) => new ClientEvent());
I simply need to map some auto generated classes from database to domain/viewmodels classes. The autogenerated class may have names like customer_id that I want to be mapped with CustomerId. Somehow I want to register my own convention with auto mapper. I have started with following code however the mapped object properties are not populated:
// Generic method that should map source to target
public static TTarget MapWithUnderScoreConvension(TSource source, TTarget target)
{
Mapper.Initialize(cfg=> cfg.AddProfile<AutoMapperUnderScoreProfile>());
Mapper.CreateMap<TSource, TTarget>();
var mapped = Mapper.Map(source, target);
return mapped;
}
// New underscore profile
public class AutoMapperUnderScoreProfile : Profile
{
public AutoMapperUnderScoreProfile()
{
Mapper.Initialize(configuration => configuration.CreateProfile("UnderScoreProfile", UnderScoreProfile));
Mapper.AssertConfigurationIsValid();
}
private void UnderScoreProfile(IProfileExpression profile)
{
profile.SourceMemberNamingConvention = new PascalCaseNamingConvention();
profile.DestinationMemberNamingConvention = new SourceUnderScoreNamingConvension();
}
}
// Convention class
public class SourceUnderScoreNamingConvension : INamingConvention
{
private readonly string _separatorCharacter="_";
private readonly Regex _splittingExpression = new Regex(#"[\p{Lu}0-9]+(?=_?)");
public Regex SplittingExpression { get { return _splittingExpression;} private set{} }
public string SeparatorCharacter { get { return _separatorCharacter; } private set{} }
}
// Test cases
[TestMethod()]
public void Test_Map_Db_Generated_Class_To_Model()
{
var dbGenerated = new QuestionTypeFromDb()
{
QuestionType_Description = "1",
QuestionType_Id = 1,
QuestionType_Is_Default = true,
QuestionType_Is_TimeBased = true,
QuestionType_Sequence = 1,
QuestionType_Time_In_Seconds = 1
};
var mappedObject = AutoMapperHelper<QuestionTypeFromDb, QuestionType>
.MapWithUnderScoreConvension(dbGenerated, new QuestionType());
mappedObject.QuestionTypeId.Should().Be(dbGenerated.QuestionType_Id);
mappedObject.QuestionTypeDescription.Should().Be(dbGenerated.QuestionType_Description);
mappedObject.TimeInSeconds.Should().Be(dbGenerated.QuestionType_Time_In_Seconds);
mappedObject.QuestionTypeSequence.Should().Be(dbGenerated.QuestionType_Sequence);
}
public class TestQuestionWithAnswerType
{
public int QuestionTypeId { get; set; }
public string QuestionTypeDescription { get; set; }
public int QuestionTypeSequence { get; set; }
public bool QuestionTypeIsTimeBased { get; set; }
public int? QuestionTypeTimeInSeconds { get; set; }
public bool QuestionTypeIsDefault { get; set; }
}
any comments will be appreciated.
Update
I have found that the following workaround works:
I simply replaced used this -> to replace 'underscore' with nothing (Mapper.Initialize(c => c.ReplaceMemberName("_", ""));
public static TTarget MapWithUnderScoreConvension(TSource source, TTarget target)
{
Mapper.Initialize(c => c.ReplaceMemberName("_", ""));
//Mapper.Initialize(cfg => cfg.AddProfile<AutoMapperUnderScoreProfile>());
Mapper.CreateMap<TSource, TTarget>();
var mapped = Mapper.Map(source, target);
return mapped;
}
Your regex needs to be changed to : [\p{L}}0-9]+(?=_?)
This will take care of Customer_Id, CUSTOMER_ID, customer_id
The {L} unicode category includes Lu, Lt, Ll, Lm and Lo characters as mentioned here.
Answer is added in the Update section of the question. Basically the solution for me was very simple -> Mapper.Initialize(c => c.ReplaceMemberName("_", ""));
I'm using PrimeFaces to display information in a DataTable. The data in the datatable is actually a List of entity objects which is generated by OpenJPA. And the entities have relations to other entities. This means that there are Lists inside Lists.
For example, an entity called Authors, which has many Books. The data List<Authors> is listed in the datatable. And in order to sort the List i use Collections.sort() which of course doesn't work when i try to sort on the Authors book title. Because the title field is an instance of the Book class.
How do i go about to sort the Lists when there are relationships like this?
Thanks in advance.
Here is an example of sorting by books title, you need to sort your books list :
public static void main(String args[]) {
List<Author> list = new ArrayList<Author>();
for (int i=0;i<5;i++){
Author a = new Author();
a.setName("author"+i);
List<Book> books = new ArrayList<Book>();
for(int j=0;j<4;j++){
Random r = new Random();
char c = (char) (r.nextInt(26) + 'a');
Book b = new Book();
b.setTitle(c+"title");
books.add(b);
}
a.setBooks(books);
list.add(a);
}
/*
* At this point of time you have Authors list which you want to sort by book title.
* So you can do something like below if you want to do it through Collections.sort
*/
for(Author a : list){
Collections.sort(a.getBooks(), new Comparator<Book>(){
#Override
public int compare(Book o1, Book o2) {
return o1.getTitle().compareToIgnoreCase(o2.getTitle());
}});
}
System.out.println(list);
}
Author and Book used in above example:
import java.util.List;
public class Author {
private List<Book> books;
private String name;
#Override
public String toString() {
return "Author [books=" + books + ", name=" + name + "]";
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Book.java:
public class Book {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Override
public String toString() {
return "Book [title=" + title + "]";
}
}
I have an interface iExportColumn and a class ExportColumn implementing the interfce. ExportColumnCollection class should be generic for all the classes that implements IExportColumn interface.
public interface IExportColumn
{
string Header { get; set; }
string ColumnName { get; set; }
}
public class ExportColumn : IExportColumn
{
public ExportColumn(){}
public string Header { get; set; }
public string ColumnName { get; set; }
}
public class ExportColumnCollection<T> where T: IExportColumn
{
private List<T> cols;
public ExportColumnCollection (List<T> c)
{
cols = c;
}
public T Columninfo (string colname)
{
}
.....
}
I am getting run time error saying could not load type ExportColumnCollection.
I am looking for something to achieve somthing like
List<IExportColumn> = new List<ExportColumn>();
I have two classes implementing the interfaces IExportColumn and I need to hold a GenericCollection to handle List
The proper usage for your class would be:
List<IExportColumn> list= new List<IExportColumn>();
// you may add to the collection any class which implements IExportColumn
list.Add(new ExportColumn1() { ColumnName = "Id" });
list.Add(new ExportColumn2() { ColumnName = "Value" });
ExportColumnCollection<IExportColumn> collection = new
ExportColumnCollection<IExportColumn>(list);
var colInfo = collection.ColumnInfo("Id");
I have this code:
[Serializable]
[XmlRoot("ISO_CCY_CODES")]
public class IsoCurrencyCodes
{
public IsoCurrencyCodes()
{
IsoCodes = new List<IsoCurrencyCode>();
}
public IsoCurrencyCodes(List<IsoCurrencyCode> isoCodes)
{
IsoCodes = isoCodes;
}
[XmlArrayItem("ISO_CURRENCY")]
public List<IsoCurrencyCode> IsoCodes { get; set; }
public static IEnumerable<IsoCurrencyCode> Get()
{
var doc = XDocument.Parse(XmlStringIsoCodes.XmlSource.Replace("\r\n", ""));
var res = doc.Deserialize<IsoCurrencyCodes>();
return res.IsoCodes;
}
}
[Serializable]
[XmlRoot("ISO_CURRENCY")]
public class IsoCurrencyCode
{
public IsoCurrencyCode()
{
}
[XmlElement(ElementName = "ENTITY")]
public string Entity { get; set; }
[XmlElement(ElementName = "CURRENCY")]
public string Currency { get; set; }
[XmlElement(ElementName = "ALPHABETIC_CODE")]
public string Alpha_Code3 { get; set; }
[XmlElement(ElementName = "NUMERIC_CODE")]
public int NumCode { get; set; }
[XmlElement(ElementName = "MINOR_UNIT")]
public string MinorUnit { get; set; }
}
And this code, for deserialization:
public static XDocument Serialize<T>(this T source)
{
var ser = new XmlSerializer(source.GetType());
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
ser.Serialize(writer, source);
}
return XDocument.Parse(sb.ToString());
}
public static T Deserialize<T>(this XDocument xmlDocument)
{
var xmlSerializer = new XmlSerializer(typeof (T));
using (var reader = xmlDocument.CreateReader())
return (T) xmlSerializer.Deserialize(reader);
}
This is the XML source
But deserialization doesn't work. Please help.
Thanks!
I believe you only want to use XMLArray if you have a collection element for all of the items to sit underneath. For example here it could be ISO_CURRENCIES. I'm assuming you can't change the source in this case, so just use this instead:
[XmlElement("ISO_CURRENCY")]
public List<IsoCurrencyCode> IsoCodes { get; set; }
You should find that works.
Additionally, if you find you have further problems in getting the deserialization classes right, you can have them autogenerated for you from the XML and then you can take a look at the code that is created:
xsd source.xml
xsd source.xsd /c
This will create source.cs which you can then use in your project or adapt for your own uses.
As a further note, you'll find you can't use int for Minor_Unit as it's nullable (look at ANTARCTICA). You can't deserialize straight to an int?, so you'll either have to make it a string or go via another property, look at this question for more information.