Отображения модели в ViewModel не передаются дочерним объектам

1

Я новичок в AutoMapper, но я прочитал несколько руководств и решил попробовать. В этих учебниках была хорошая идея, которую я решил принять. Авторитет предположил, что код отображения для модели представления должен оставаться в модели представления, а не в конфигурации 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
{

}

Спасибо заранее за любые предложения.

Теги:
reflection
asp.net-mvc
inheritance
automapper

1 ответ

1

Вы можете создать защищенный метод в вашем базовом классе, который создает настраиваемые сопоставления

protected virtual IMappingExpression<BasicAddressViewModel, TDestination> CreateBaseMappings<TDestination>(IMappingExpression<BasicAddressViewModel, TDestination> mappingExpression) 
    where TDestination : BasicAddressViewModel 
и сделать virtual метод CreateMappings(IConfiguration configuration) virtual чтобы вы могли override его в производном классе и вызвать базовый метод CreateBaseMappings который возвращает IMappingExpression<BasicAddressViewModel, TDestination> что означает, что вы можете добавить больше сопоставлений для других участников

EDIT Я нашел лучшее решение. :)
Начиная с AutoMapper 2.0 вы можете использовать IncludeBase<BaseModel, BaseViewModel>() для вызова сопоставления для базового типа. Таким образом, новое решение - сделать ваш метод CreateMappings(IConfiguration configuration) virtual в базовом классе ViewModel и переопределить его в производном классе, где вы вызываете:

configuration.CreateMap().IncludeBase();

Ещё вопросы

Сообщество Overcoder
Наверх
Меню