How to scan and auto-configure profiles in AutoMap

2020-02-17 05:32发布

Is there any way to auto-configue Automapper to scan for all profiles in namespace/assembly? What I would like to do is to add mapping profiles to AutoMapper from given assembly filtered by given interface, something like Scan Conventions in 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);            
    }

I've tried to use SelfConfigure but can't find any documentation on how to use it to filter out profiles:

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

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

Another question is how can I report all maps/profiles already initialized (something like ObjectFactory.WhatDoIHave() in StructureMap)?

7条回答
SAY GOODBYE
2楼-- · 2020-02-17 05:59

I found this post while searching as well, but this is how I implemented an auto mapping scheme:

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);
        }
    }
}

So when my application starts, all I call is

AutoMapperConfiguration.Configure(); 

And all my maps are registered.

查看更多
Bombasti
3楼-- · 2020-02-17 06:06
 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);
    }
}
查看更多
女痞
4楼-- · 2020-02-17 06:10

Similar to @Martino's answer, but with a MapperConfiguration object. This will add all profiles from the assembly that contains the type MyProfile.

var config = new MapperConfiguration(cfg =>
   {
      cfg.AddProfiles(typeof(MyProfile));
   });
var mapper = config.CreateMapper();
查看更多
smile是对你的礼貌
5楼-- · 2020-02-17 06:16

Yeah, that would be fantastic...and exactly what I'm overhauling for V2. Scanning, registration, conventions etc.

There's not a good "What do I have" feature, but I think it would definitely be worth adding.

查看更多
We Are One
6楼-- · 2020-02-17 06:16

In .NET Core:

    services.AddSingleton(this.CreateMapper());
    //...
    private IMapper CreateMapper()
            => new MapperConfiguration(config => config.AddMaps(Assembly.Load("Your.Project.App")))
            .CreateMapper();
查看更多
看我几分像从前
7楼-- · 2020-02-17 06:18

In the latest versions of AutoMapper it's possible to register multiple Profile scanning one or more assemblies :

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

Tested with AutoMapper v. 6.0.2.0

查看更多
登录 后发表回答