我是AutoMapper的新手,但我已经阅读了一些教程,并决定尝试一下。 在那些教程中,我决定采用一个好主意。 authir建议视图模型的映射代码应保留在视图模型中,而不是AutoMapper配置中。这将使它更小,更容易阅读:
以下是使用反射执行此操作的基本文件, 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);
}
IMapFrom 和 IHaveCustom 接口仅用于标记映射类。现在我们来到有趣的部分。当我这样做时,如下面的
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));
}
}
我正在 CreateMappings 方法中设置映射但是如果我决定将此类用作父类,那么这些映射将无法用于我的子类,因此我将不得不重用它我所有孩子班的代码:
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));
}
}
实际上我想要实现的是
public class IndexAddressViewModel : BasicAddressViewModel
{
}
提前感谢任何建议。
答案 0 :(得分:1)
您可以在基类中创建一个用于创建自定义映射的受保护方法
protected virtual IMappingExpression<BasicAddressViewModel, TDestination> CreateBaseMappings<TDestination>(IMappingExpression<BasicAddressViewModel, TDestination> mappingExpression)
where TDestination : BasicAddressViewModel
并制作CreateMappings(IConfiguration configuration)
方法virtual
,以便您可以在派生类中override
并调用返回CreateBaseMappings
的基本IMappingExpression<BasicAddressViewModel, TDestination>
方法,这意味着您可以添加更多其他成员的映射
修改强>
我找到了更好的解决方案。 :)
从AutoMapper 2.0开始,您可以使用IncludeBase<BaseModel, BaseViewModel>()
来调用基本类型的映射。因此,新的解决方案是在基础ViewModel类中创建CreateMappings(IConfiguration configuration)
方法virtual
,并在您调用的派生类中覆盖它:
configuration.CreateMap().IncludeBase();