I'm new with AutoMapper but I've read a few tutorials and decided to try it. In those tutorials there was a good idea which I decided to adopt. The authir suggested that the mapping code for the view model should stay in the view model and not in the AutoMapper configuration. This will make it smaller and easily readable:
Here are the base files to do this using reflections, AutoMapperConfiguration:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AutoMapper;
public class AutoMapperConfig
{
private Assembly assembly;
public AutoMapperConfig(Assembly assembly)
{
this.assembly = assembly;
}
public void Execute()
{
var types = this.assembly.GetExportedTypes();
LoadStandardMappings(types);
LoadCustomMappings(types);
}
private static void LoadStandardMappings(IEnumerable<Type> types)
{
var maps = from t in types
from i in t.GetInterfaces()
where i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>) && !t.IsAbstract && !t.IsInterface
select new { Source = i.GetGenericArguments()[0], Destination = t };
foreach (var map in maps)
{
Mapper.CreateMap(map.Source, map.Destination);
}
}
private static void LoadCustomMappings(IEnumerable<Type> types)
{
var maps = from t in types
from i in t.GetInterfaces()
where typeof(IHaveCustomMappings).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface
select (IHaveCustomMappings)Activator.CreateInstance(t);
foreach (var map in maps)
{
map.CreateMappings(Mapper.Configuration);
}
}
}
public interface IMapFrom<T>
{
}
public interface IHaveCustomMappings
{
void CreateMappings(IConfiguration configuration);
}
The IMapFrom and IHaveCustom interfaces are here only to mark the mapping classes. Now we come to the interesting part. When I do for example a class like the following
public class BasicAddressViewModel : IHaveCustomMappings
{
public string Id { get; set; }
[Display(Name = "Name")]
public string Label { get; set; }
[Display(Name = "Number")]
public string Location { get; set; }
public void CreateMappings(IConfiguration configuration)
{
var map = configuration.CreateMap<Address, BasicAddressViewModel>();
map.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id));
map.ForMember(dest => dest.Label, opt => opt.MapFrom(src => src.Label));
map.ForMember(dest => dest.Location, opt => opt.MapFrom(src => src.Location));
}
}
I'm setting the mappings in the CreateMappings method but if I decide to use this class as a parent those mappings will not be available to my child class and therefor I will have to reuse the same code for all my children classes:
public class IndexAddressViewModel : BasicAddressViewModel
{
public void CreateMappings(IConfiguration configuration)
{
var map = configuration.CreateMap<Address, IndexAddressViewModel >();
map.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id));
map.ForMember(dest => dest.Label, opt => opt.MapFrom(src => src.Label));
map.ForMember(dest => dest.Location, opt => opt.MapFrom(src => src.Location));
}
}
In reality what I want to achieve is this
public class IndexAddressViewModel : BasicAddressViewModel
{
}
Thanks in advance for any suggestions.
Aucun commentaire:
Enregistrer un commentaire