模型到ViewModel映射没有传递给子对象

时间:2015-01-19 23:42:17

标签: c# asp.net-mvc inheritance reflection automapper

我是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
{

}

提前感谢任何建议。

1 个答案:

答案 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();