I have a service Class list with two Class inside:
public class ParentClass
{
public ChildClass A { get; set; }
public ChildClass2 B { get; set; }
}
public class ChildClass
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ChildClass2
{
public string Color { get; set; }
public string Nick { get; set; }
}
And I would want mapping with AutoMapper into list that have the same properties that Child's Class:
public class DTOClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public string Nick { get; set; }
}
It work fine:
My config:
Mapper.CreateMap<ChildClass, DTOClass>();
Mapper.CreateMap<ChildClass2, DTOClass>();
My code:
List<ParentClass> listParentClass = getListParentClass();
List<DTOClass> listDtoClass = new List<DTOClass>();
ParentClass dtoClass = new ParentClass();
foreach (var parentClass in listParentClass)
{
dtoClass = AutoMapper.Mapper.Map<ChildClass, DTOClass >(parentClass.A);
AutoMapper.Mapper.Map<ChildClass2, DTOClass >(parentClass.B, dtoClass);
listDtoClass.Add(dtoClass);
}
Would I like to remove the foreach, can I?
I searched about Mapping with Child's Class, Mapping with multiple Class to one Class, no success.
I tried configurate it with ForAllMembers, but not work:
Mapper.CreateMap<ParentClass, DTOClass>()
.ForAllMembers(op => op.MapFrom(s => Mapper.Map<ChildClass, DTOClass>(s.A)));
I'm not especialist into AutoMapper, if sameone could help me. I would appreciate.
You can do this:
public class ParentClass
{
public ChildClass A { get; set; }
public ChildClass2 B { get; set; }
}
public class ChildClass
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ChildClass2
{
public string Color { get; set; }
public string Nick { get; set; }
}
public class DTOClass
{
public int AId { get; set; }
public string AName { get; set; }
public string BColor { get; set; }
public string BNick { get; set; }
}
Your mapping:
cfg.CreateMap<ChildClass, DTOClass>();
cfg.CreateMap<ChildClass2, DTOClass>();
cfg.CreateMap<ParentClass, DTOClass>();
Your example:
List<ParentClass> listParentClass = getListParentClass();
//List<DTOClass> listDtoClass = new List<DTOClass>();
var listDtoClass = AutoMapper.Mapper.Map<List<DTOClass>>(listParentClass);
Related
In my CollectionService class i want to be able to use either DatabaseWatchService or RemoteFilesWatchService therefore I used IWatchService<IEntity> watchService parameter which should be common for both. Nevertheless in DoIt() when i try to use either one of the class i am having following error:
Cannot implicitly convert type 'RemoteFilesWatchService' to
'IWatchService'. An explicit conversion exists (are you missing a
cast?)
How to fix that to able to use in CollectionService either one mentioned class or another.
This is the full code:
public interface IWatch
{
void Watch();
}
public interface IWatchService<TDataEntity> where TDataEntity : IEntity
{
INotificationFactory NotificationFactory { get; }
ObservableCollection<TDataEntity> MatchingEntries { get; set; }
}
public interface IDatabaseWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IDatabaseEntity
{
IDatabaseRepository<IDbManager> DatabaseRepository { get; }
}
public interface IRemoteFilesWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IFileEntity
{
List<string> ExistingRemoteFiles { get; set; }
List<RemoteLocation> RemoteLocations { get; set; }
IWinScpOperations RemoteManager { get; set; }
IRemoteFilesRepository<IDbManager, TDataEntity> RemoteFilesRepository { get; }
}
public class RemoteFilesWatchService : IRemoteFilesWatchService<IFileEntity>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<IFileEntity> MatchingEntries { get; set; }
public List<string> ExistingRemoteFiles { get; set; }
public List<RemoteLocation> RemoteLocations { get; set; }
public IWinScpOperations RemoteManager { get; set; }
public IRemoteFilesRepository<IDbManager, IFileEntity> RemoteFilesRepository { get; }
public RemoteFilesWatchService(IWinScpOperations remoteOperator,
IRemoteFilesRepository<IDbManager, IFileEntity> remoteFilesRepository,
INotificationFactory notificationFactory)
{
RemoteManager = remoteOperator;
RemoteFilesRepository = remoteFilesRepository; //csv, xml or other repo could be injected
NotificationFactory = notificationFactory;
}
public void Watch()
{
}
}
public class DatabaseWatchService : IDatabaseWatchService<DatabaseQuery>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<DatabaseQuery> MatchingEntries { get; set; }
public IDatabaseRepository<IDbManager> DatabaseRepository { get; }
public DatabaseWatchService(IDatabaseRepository<IDbManager> databaseRepository,
INotificationFactory notificationFactory)
{
DatabaseRepository = databaseRepository;
NotificationFactory = notificationFactory;
}
public void Watch()
{
}
}
public class CollectionService
{
private IWatchService<IEntity> _watchService;
public CollectionService(IWatchService<IEntity> watchService)
{
_watchService = watchService;
}
}
class Run
{
void DoIt()
{
IWatchService<IEntity> fileWatcherServiceCsv = new RemoteFilesWatchService(new WinScpOperations(),
new RemoteCsvFilesRepository(new DbManager(ConnectionDbType.MySql)),
new NotificationFactory());
var coll1 = new CollectionService(fileWatcherServiceCsv);
}
}
public interface IEntity
{
}
public interface IFileEntity : IEntity
{
int Id { get; set; }
string Name { get; set; }
bool IsActive { get; set; }
bool RemoveFromSource { get; set; }
string DestinationFolder { get; set; }
RemoteLocation RemoteLocation { get; set; }
}
public interface IDatabaseEntity : IEntity
{
}
public class CsvFile : IFileEntity
{
public int ColumnHeader { get; set; }
public int ColumnsCount { get; set; }
public string Separator { get; set; }
public int ValuesRowStartposition { get; set; }
public int ColumnRowPosition { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
}
public class XmlFile : IFileEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
public string SubNode { get; set; }
public string MainNode { get; set; }
}
Rather than having IWatchService expose a concrete type, I'd suggest instead having it require reimplementation of those interfaces from ObservableCollection that you actually want the consumers to use (or move those onto another interface and have that be what MatchingEntries returns).
Here I've guessed that the consumers want the events that the observable collection raises and to be able to enumerate the collection and that's all, which means we can a) implement those interfaces and b) make the interface covariant:
public interface IWatchService<out TDataEntity> :
INotifyCollectionChanged,
INotifyPropertyChanged,
IEnumerable<TDataEntity>
where TDataEntity : IEntity
{
INotificationFactory NotificationFactory { get; }
}
Now, if the implementations choose to use an ObservableCollection and just use simple wrappers to implement those interfaces or choose to satisfy the interface in some other way has been move back into an implementation decision.
I currently working with .net core 2.1 and try to use automapper for nested objects to convert model to dto and dto to model. When every field is mapped correctly issue appears with relationship mapping.
Models
public class DropdownValue
{
public int Id { get; set; }
public string Value { get; set; }
public int PropertyId { get; set; }
public Property Property { get; set; }
}
public class Property
{
public int Id { get; set; }
public string Title { get; set; }
public ValueTypes ValueType { get; set; }
public InputTypes InputType { get; set; }
public List<DropdownValue> DropdownValues { get; set; }
}
Dtos
public class DropdownValueDto
{
public int Id { get; set; }
public string Value { get; set; }
public PropertyDto Property { get; set; }
}
public class PropertyDto
{
public int Id { get; set; }
public string Title { get; set; }
public InputTypes InputType { get; set; }
public ValueTypes ValueType { get; set; }
}
Mapper
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Property, PropertyDto>();
CreateMap<DropdownValue, DropdownValueDto>();
}
}
Usage in handler
_mapper.Map<List<Models.DropdownValue>, List<DropdownValueDto>>(dropdownValues)
I always use automapper mapping tool in .net 4x framework projects but when i develop .net core projects, i always use and recommend mapster mapping tool. It is pretty fast and simple ! Benchmark Results It also solves your problem. You can check the example usage where is below.
First create a mapper class.
public static class Mapper
{
public static void CreateMap()
{
TypeAdapterConfig<Property, PropertyDto>
.NewConfig();
TypeAdapterConfig<DropdownValue, DropdownValueDto>
.NewConfig();
}
}
Initialize in startup
public Startup(IHostingEnvironment env)
{
// other stuffs
// Mapping
Mapper.CreateMap();
}
Usage
dropdownValues.Adapt<List<Models.DropdownValue>, List<DropdownValueDto>>()
//Models
public class DropdownValue
{
public int Id { get; set; }
public string Value { get; set; }
public int PropertyId { get; set; }
public Property Property { get; set; } = new Property();
}
public class Property
{
public int Id { get; set; }
public string Title { get; set; }
public ValueTypes ValueType { get; set; } = new ValueTypes();
public InputTypes InputType { get; set; } = new InputTypes();
public List<DropdownValue> DropdownValues { get; set; } = new List<DropdownValue>();
}
//Dtos
public class DropdownValueDto
{
public int Id { get; set; }
public string Value { get; set; }
public PropertyDto Property { get; set; } = new PropertyDto();
}
public class PropertyDto
{
public int Id { get; set; }
public string Title { get; set; }
public InputTypes InputType { get; set; } = new InputTypes();
public ValueTypes ValueType { get; set; } = new ValueTypes();
}
I want to create a class that have a class but this second class may be different each time the first class is called. For example:
public class ServerResponseObject
{
public string statusCode { get; set; }
public string errorCode { get; set; }
public string errorDescription { get; set; }
public Object obj { get; set; }
public ServerResponseObject(Object obje)
{
obj = obje;
}
}
public class TVChannelObject
{
public string number { get; set; }
public string title { get; set; }
public string FavoriteChannel { get; set; }
public string description { get; set; }
public string packageid { get; set; }
public string format { get; set; }
}
public class ChannelCategoryObject
{
public string id { get; set; }
public string name { get; set; }
}
How can I do it to call the ServerResponseObject with different objects each time, once with TVChannelObject and once with ChannelCategoryObject?
What you're looking for is a generic type parameter:
public class ServerResponseObject<T>
{
public ServerResponseObject(T obj)
{
Obj = obj;
}
public T Obj { get; set; }
}
I'm using the Petfinder API and trying to return a root object in my C# code. I used the Json class generator to generate the classes, but the Deserialize function is returning nulls.
This is my C# code:
using (var client = new WebClient())
{
var json = new WebClient().DownloadString("http://api.petfinder.com/shelter.getPets?format=json&key=<key>&id=<id>");
Petfinder deserializedPet = JsonConvert.DeserializeObject<Petfinder>(json);
}
The Petfinder object is defined as:
internal class Petfinder
{
[JsonProperty("#xmlns:xsi")]
public string XmlnsXsi { get; set; }
[JsonProperty("lastOffset")]
public LastOffset LastOffset { get; set; }
[JsonProperty("pets")]
public Pets Pets { get; set; }
[JsonProperty("header")]
public Header Header { get; set; }
[JsonProperty("#xsi:noNamespaceSchemaLocation")]
public string XsiNoNamespaceSchemaLocation { get; set; }
}
The first few lines of the json string is as follows:
{"#encoding":"iso-8859-1","#version":"1.0","petfinder":{"#xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","lastOffset":{"$t":"25"},"pets":{"pet":[{"options":{"option":[{"$t":"hasShots"},{"$t":"altered"},{"$t":"housetrained"}]},"breeds":{"breed":{"$t":"Domestic Medium Hair"}},"shelterPetId":{},"status":{"$t":"A"},"name":{"$t":"Jasmine"},...
If that helps at all.
I'm a newbie to json.net. What am I doing wrong?
Your class is wrong, take a look at the output from json2csharp.com for the example json you provided. Obviously the __invalid_name_$t needs to be manually fixed and the mapped using [JsonProperty].
public class LastOffset
{
public string __invalid_name__$t { get; set; }
}
public class Option
{
public string __invalid_name__$t { get; set; }
}
public class Options
{
public List<Option> option { get; set; }
}
public class Breed
{
public string __invalid_name__$t { get; set; }
}
public class Breeds
{
public Breed breed { get; set; }
}
public class ShelterPetId
{
}
public class Status
{
public string __invalid_name__$t { get; set; }
}
public class Name
{
public string __invalid_name__$t { get; set; }
}
public class Pet
{
public Options options { get; set; }
public Breeds breeds { get; set; }
public ShelterPetId shelterPetId { get; set; }
public Status status { get; set; }
public Name name { get; set; }
}
public class Pets
{
public List<Pet> pet { get; set; }
}
public class Petfinder
{
public string __invalid_name__#xmlns:xsi { get; set; }
public LastOffset lastOffset { get; set; }
public Pets pets { get; set; }
}
public class RootObject
{
public string __invalid_name__#encoding { get; set; }
public string __invalid_name__#version { get; set; }
public Petfinder petfinder { get; set; }
}
I am trying to AutoMapper to EF models which are nested inside nested.
For Example in below code categorySrc, languageSrc, abstractSrc..etc and categoryDest, languageDest, abstractDest ..etc classes are same.
Now I am trying to Map categorySrc to categoryDest, So I made like below, if throwing an error
Is something I am doing wrong here?
var categoryData = abstractContext.GetCategoryByCatId(catId);
Mapper.CreateMap<Models.categoryDest, categorySource>();
Mapper.CreateMap<languageDest, Models.languageSource>();
Mapper.CreateMap<#abstractDest, Models.#abstractSrc>();
Mapper.CreateMap<abstract_categoryDest, Models.abstract_categorySrc>();
Mapper.CreateMap<questionDest, Models.questionSrc>();
Mapper.CreateMap ... //For other objects
Mapper.CreateMap ...//For other objects
Mapper.AssertConfigurationIsValid(); //Error occurring here
var category = Mapper.Map<category,Models.category>(categoryData);
Classes:
public partial class categoryDest
{
public int category_id { get; set; }
public int language_id { get; set; }
public virtual languageDest language { get; set; }
}
public partial class languageDest
{
public language()
{
this.abstracts = new HashSet<#abstractDest>();
this.abstract_category = new HashSet<abstract_categoryDest>();
this.categories = new HashSet<categoryDest>();
this.questions = new HashSet<questionDest>();
}
public int language_id { get; set; }
public string language_name { get; set; }
public string language_locale_code { get; set; }
public virtual ICollection<#abstractDest> abstracts { get; set; }
public virtual ICollection<abstract_categoryDest> abstract_category { get; set; }
public virtual ICollection<categoryDest> categories { get; set; }
public virtual ICollection<questionDest> questions { get; set; }
}
public partial class #abstractDest
{
public #abstract()
{
this.abstract_category = new HashSet<abstract_categoryDest>();
this.abstract_fields = new HashSet<abstract_fieldsDest>();
this.abstract_image = new HashSet<abstract_imageDest>();
this.people = new HashSet<person>();
}
public int abstract_id { get; set; }
public int language_id { get; set; }
public string abstract_name { get; set; }
public virtual ICollection<abstract_categoryDest> abstract_category { get; set; }
public virtual ICollection<abstract_fieldsDest> abstract_fields { get; set; }
public virtual ICollection<abstract_imageDest> abstract_image { get; set; }
public virtual languageDest language { get; set; }
public virtual ICollection<personDest> people { get; set; }
}
How to do this complex mapping?