AutoMapper как избежать инициализации

#c# #automapper

#c# #automapper

Вопрос:

Как мне избежать требования подобного кода:

 public static class BusinessLogicAutomapper
{
    public static bool _configured;

    public static void Configure()
    {
        if (_configured)
            return;

        Mapper.CreateMap<Post, PostModel>();
        _configured = true;
    }
}
  

в моей сборке BL и необходимости вызывать Configure() из моей Global.asax в моем приложении MVC?

Я имею в виду, я ожидаю вызова, подобного этому:

     public PostModel GetPostById(long id)
    {
        EntityDataModelContext context = DataContext.GetDataContext();
        Post post = context.Posts.FirstOrDefault(p => p.PostId == id);

        PostModel mapped = Mapper.Map<Post, PostModel>(post);
        return mapped;
    }
  

чтобы Mapper.Map<TIn,TOut> создать mapper, если его не существует, вместо того, чтобы создавать его самому вручную (я даже не должен знать об этой внутренней работе). Как я могу обойти декларативное создание картографов для AutoMapper?

Было бы желательно решение, естественное для AutoMapper, но расширение или какое-либо архитектурное изменение, чтобы избежать этой инициализации, тоже сработало бы.

Я использую MVC 3, .NET 4 и не использую IoC / DI (по крайней мере, пока)

Комментарии:

1. Если у вас нет вызова конфигурации CreateMap, что должно произойти, когда что-то не отображается в Post -> PostModel map? То есть вы переименовали что-то в Post, но не переименовали это в PostModel?

Ответ №1:

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

Я использую небольшую утилиту, подобную той, которую вы хотите автоматизировать в моей среде аудита, для копирования данных из модели сущности в связанную с ней модель аудита. Я создал его до того, как начал использовать AutoMapper, и не заменил его. Я называю это ReflectionHelper, приведенный ниже код является его модификацией (из памяти) — он обрабатывает только простые свойства, но при необходимости может быть адаптирован для поддержки вложенных моделей и коллекций. Это основано на соглашении, предполагающем, что свойства с одинаковым именем соответствуют и имеют одинаковый тип. Свойства, которые не существуют для копируемого типа, просто игнорируются.

 public static class ReflectionHelper
{
      public static T CreateFrom<T,U>( U from )
          where T : class, new
          where U : class
      {
            var to = Activator.CreateInstance<T>();
            var toType = typeof(T);
            var fromType = typeof(U);

            foreach (var toProperty in toType.GetProperties())
            {
                var fromProperty = fromType.GetProperty( toProperty.Name );
                if (fromProperty != null)
                {
                   toProperty.SetValue( to, fromProperty.GetValue( from, null), null );
                }
            }

            return to;
      }
  

Используется как

     var model = ReflectionHelper.CreateFrom<ViewModel,Model>( entity );

    var entity = ReflectionHelper.CreateFrom<Model,ViewModel>( model );
  

Оригинал

Я выполняю свое отображение в статическом конструкторе. Mapper инициализируется при первом обращении к классу без необходимости вызова каких-либо методов. Однако я не делаю логический класс статическим, чтобы улучшить его тестируемость и тестируемость классов, использующих его в качестве зависимости.

 public class BusinessLogicAutomapper
{
    static BusinessLogicAutomapper
    {
        Mapper.CreateMap<Post, PostModel>();
        Mapper.AssertConfigurationIsValid();
    }
}
  

Ответ №2:

ознакомьтесь с профилями Automapper.

У меня есть эта настройка в моем Global.asax — она выполняется один раз статически, поэтому все настроено во время выполнения и готово к работе.

У меня также есть 1 модульный тест, который охватывает все карты, чтобы проверить их правильность.

Хорошим примером этого является блог Ayendes Raccoon

https://github.com/ayende/RaccoonBlog