Как сканировать и настраивать профили в AutoMapper?

17

Есть ли способ автонастройки Automapper для сканирования всех профилей в пространстве имен / сборке? То, что я хотел бы сделать, это добавить профили сопоставления в AutoMapper из данной сборки, отфильтрованной данным интерфейсом, что-то вроде соглашений об обнаружении в StructureMap:

    public static void Configure()
    {
        ObjectFactory.Initialize(x =>
            {
                // Scan Assembly
                x.Scan(
                    scanner =>
                    {
                        scanner.TheCallingAssembly();
                        scanner.Convention<MyCustomConvention>();
                        scanner.WithDefaultConventions();
                    });

                // Add Registries
                x.AddRegistry(new SomeRegistry());
            });

        Debug.WriteLine(ObjectFactory.WhatDoIHave());
    }

public class MyCustomConvention : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        if (!type.CanBeCastTo(typeof(IMyType)))
        {
            return;
        }

        string name = type.Name.Replace("SomeRubishName", String.Empty);
        registry.AddType(typeof(IMyType), type, name);            
    }

Я попытался использовать SelfConfigure, но не могу найти документацию о том, как использовать его для фильтрации профилей:

    public static void Configure()
    {
        Mapper.Initialize(x =>
                              {
                                  // My Custom profile
                                  x.AddProfile<MyMappingProfile>();

                                  // Scan Assembly
                                  x.SelfConfigure(Assembly.GetCallingAssembly());
                              });
    }

Другой вопрос: как я могу сообщить обо всех уже инициализированных картах / профилях (что-то вроде ObjectFactory.WhatDoIHave () в StructureMap)?

    
задан Wojciech Markowski 16.04.2010 в 10:34
источник

5 ответов

31

Я тоже нашел этот пост при поиске, но именно так я реализовал схему автоматического сопоставления:

public class MyCustomMap : Profile
{
    protected override void Configure()
    {
        CreateMap<MyCustomViewModel, MyCustomObject>()
            .ForMember(dest => dest.Phone,
                        opt => opt.MapFrom(
                        src => src.PhoneAreaCode + src.PhoneFirstThree + src.PhoneLastFour));
    }
}

public static class AutoMapperConfiguration
{
    public static void Configure()
    {
        Mapper.Initialize(x => GetConfiguration(Mapper.Configuration));
    }

    private static void GetConfiguration(IConfiguration configuration)
    {
        var profiles = typeof(MyCustomMap).Assembly.GetTypes().Where(x => typeof(Profile).IsAssignableFrom(x));
        foreach (var profile in profiles)
        {
            configuration.AddProfile(Activator.CreateInstance(profile) as Profile);
        }
    }
}

Итак, когда мое приложение запускается, все, что я вызываю, это

AutoMapperConfiguration.Configure(); 

И все мои карты зарегистрированы.

    
ответ дан Jason More 01.09.2010 в 15:11
источник
6

Да, это было бы фантастически ... и именно то, что я перестраиваю для V2. Сканирование, регистрация, соглашения и т. Д.

Нет хорошей функции «Что у меня есть», но я думаю, что это определенно стоит добавить.

    
ответ дан Jimmy Bogard 16.04.2010 в 14:47
источник
4

В последних версиях AutoMapper можно зарегистрировать несколько Profile для сканирования одной или нескольких сборок:

 Mapper.Initialize(x => x.AddProfiles(typeof(MyMappingProfile).Assembly));

Протестировано с помощью AutoMapper v. 6.0.2.0

    
ответ дан Martino Bordin 06.05.2017 в 18:32
источник
1

У меня это так, не знаю, лучший ли это, но он очень хорошо работает на довольно большом проекте.

public class AutoMapperGlobalConfiguration : IGlobalConfiguration
    {
        private AutoMapper.IConfiguration _configuration;

        public AutoMapperGlobalConfiguration(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public void Configure()
        {
            //add all defined profiles
            var query = this.GetType().Assembly.GetExportedTypes()
                .Where(x => x.CanBeCastTo(typeof(AutoMapper.Profile)));

            _configuration.RecognizePostfixes("Id");

            foreach (Type type in query)
            {
                _configuration.AddProfile(ObjectFactory.GetInstance(type).As<Profile>());
            }

            //create maps for all Id2Entity converters
            MapAllEntities(_configuration);

           Mapper.AssertConfigurationIsValid();
        }

        private static void MapAllEntities(IProfileExpression configuration)
        {
            //get all types from the SR.Domain assembly and create maps that
            //convert int -> instance of the type using Id2EntityConverter
            var openType = typeof(Id2EntityConverter<>);
            var idType = typeof(int);
            var persistentEntties = typeof(SR.Domain.Policy.Entities.Bid).Assembly.GetTypes()
               .Where(t => typeof(EntityBase).IsAssignableFrom(t))
               .Select(t => new
               {
                   EntityType = t,
                   ConverterType = openType.MakeGenericType(t)
               });
            foreach (var e in persistentEntties)
            {
                var map = configuration.CreateMap(idType, e.EntityType);
                map.ConvertUsing(e.ConverterType);
            }
        }
    }
}
    
ответ дан epitka 20.04.2010 в 21:07
источник
0
 public class AutoMapperAdapter : IMapper
{
    private readonly MapperConfigurationExpression _configurationExpression =
        new MapperConfigurationExpression();

    public void AssertConfigurationIsValid() { Mapper.AssertConfigurationIsValid(); }

    public void CreateMap<TSource, TDestination>()
    {
        _configurationExpression.CreateMap<TSource, TDestination>();
    }

    public void Initialize() { Mapper.Initialize(_configurationExpression); }

    public TDestination Map<TDestination>(object source)
    {
        return Mapper.Map<TDestination>(source);
    }
}
    
ответ дан user3472484 12.10.2016 в 08:43
источник