Универсальный картограф вместо множества индивидуальных картографов - PullRequest
2 голосов
/ 27 сентября 2011

Я использую ASP.NET MVC 3 с Razor и Autofac для внедрения зависимостей.

Я думаю о создании универсального преобразователя.В настоящее время я использую AutoMapper для сопоставления моего домена и модели представления.Это может быть любая инфраструктура отображения, но я использую AutoMapper.

Вот мой IMapper интерфейс:

public interface IMapper
{
     object Map(object source, Type sourceType, Type destinationType);
}

У меня тогда есть интерфейс IBankMapper, который реализует этот интерфейс IMapper.Причина, по которой я это сделал, заключается в том, что у меня может быть много разных картографов.Используя внедрение зависимостей, я могу знать, какой экземпляр я могу внедрить.Поэтому для IBankMapper я буду внедрять BankMapper, ICategoryMapper я буду вводить CategoryMapper.

IBankMapper интерфейс:

public interface IBankMapper : IMapper
{
}

BankMapper класс:

public class BankMapper : IBankMapper
{
     static BankMapper()
     {
          Mapper.CreateMap<Bank, EditBankViewModel>();
          Mapper.CreateMap<EditBankViewModel, Bank>();
     }

     public object Map(object source, Type sourceType, Type destinationType)
     {
          return Mapper.Map(source, sourceType, destinationType);
     }
}

какпрограмма растет, как и классы картографа.Есть ли способ, которым я могу создать универсальный картограф, который можно использовать во всем приложении?Это возможно?

Ответы [ 3 ]

5 голосов
/ 27 сентября 2011

Вам абсолютно не нужно создавать какие-либо классы мапперов.

Все, что вам нужно сделать, это убедиться, что вы звоните Mapper.CreateMap в начале вашего заявления. Затем вы можете использовать Mapper.Map для составления карты.

Как правило, я создаю статический класс с одним методом для управления созданием моих Карт. Это выглядит примерно так:

public static class Transformers
{
    public static void Register()
    {
        Mapper.CreateMap<Bank, EditBankViewModel>();
        Mapper.CreateMap<EditBankViewModel, Bank>();

        Mapper.CreateMap<Account, EditAccountViewModel>();
        Mapper.CreateMap<EditAccountViewModel, Account>();

        // And so on. You can break them up into private methods
        // if you have too many.
    }
}

Затем я вызываю этот метод в Global.asax, чтобы убедиться, что он запускается при необходимости. В любом другом месте моего приложения я могу позвонить Mapper.Map для любого из настроенных сопоставлений:

protected void Application_Start()
{
    Transformers.Register();
}
4 голосов
/ 27 сентября 2011

Похоже, вы создаете эти интерфейсы, чтобы иметь возможность имитировать AutoMapper в ваших модульных тестах. Для этой цели вы можете просто использовать IMappingEngine из AutoMapper.

Ваши классы будут зависеть от IMappingEngine, который будет введен. IMappingEngine имеет те же методы, что и статический класс Mapper для сопоставления ваших объектов.

В вашем корне композиции вы должны сконфигурировать mapper и зарегистрировать механизм отображения в контейнере DI.

Примерно так:

// composition root:
Mapper.CreateMap<Bank, EditBankViewModel>();
Mapper.CreateMap<EditBankViewModel, Bank>();
builder.Register(Mapper.Engine);

// your classes:
class YourClass
{
    public YourClass(IMappingEngine mappingEngine)
    {
    }
}
1 голос
/ 27 сентября 2011

Как сказал Даниэль, Automapper уже является универсальным картографом.Если вас беспокоит прямая зависимость от autopper в вашем коде, вы можете скрыть ее за небольшим фасадом, например:

public interface IMapper
{
    TDestination Map<TSource, TDestination>(TSource source);
}
public class MyMapper :IMapper
{
    public TDestination Map<TSource, TDestination>(TSource source)
    {
        AutoMapper.Mapper.CreateMap<TSource, TDestination>();
        return AutoMapper.Mapper.Map<TSource, TDestination>(source);
    }
}

Это также может помочь вам смоделировать маппер как инъекционную зависимость

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...