向ASP.NET Core中的Automapper TypeConverter注入依赖项

Pau*_*lor 3 dependency-injection automapper asp.net-core

要获得DI框架以将依赖项注入Automapper自定义TypeConverter,通常使用ConstructServicesUsingMapperConfiguration对象的方法.因此,使用ASP.NET Core DI,我希望能够像这样配置AutoMapper:

public static IMapperConfiguration Configure(IServiceProvider provider)
{
    var config = new MapperConfiguration(cfg => {
         cfg.AddProfile<MyProfile>();
         cfg.ConstructServicesUsing(type => provider.GetService(type));
    });
    config.AssertConfigurationIsValid();
    return config;
}
Run Code Online (Sandbox Code Playgroud)

MapperConfiguration对象将在startup.cs中配置为可注入服务,因此:

public void ConfigureServices(IServiceCollection services)
{
    //other service configuration omitted for simplicity

    //Automapper config
    var provider = services.BuildServiceProvider();
    var config = AutoMapperConfig.Configure(provider);
    services.AddInstance(config);
}
Run Code Online (Sandbox Code Playgroud)

并且依赖项(在本例中为Automapper本身)将像这样注入到TypeConverter构造函数中.

public class MyConverter : ITypeConverter<ThisType, ThatType>
{
    private IMapper _mapper;

    public MyConverter(IMapperConfiguration mapperConfig)
    {
        var mc = mapperConfig as MapperConfiguration;
        _mapper = mc.CreateMapper();
    }

    public ThatType Convert(ResolutionContext context)
    {
        //do something with _mapper here
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经成功地使用了这个模式与几个DI框架,但我不能让它与ASP.NET Core一起使用.猜测,我认为可能需要在ConfigureServices方法完成后为Automapper提供由.NET构建的真实IServiceProvider实例.但是,即使我将配置的那部分推迟到Configure方法(见下文),依赖仍然不会被注入到TypeConverter中.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider provider)
{
    var config = provider.GetService<IMapperConfiguration>();
    config.ConstructServicesUsing(type => provider.GetService(type));
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:如何使用ASP.NET Core配置Automapper,以便将依赖项注入自定义TypeConverters?

Pau*_*lor 5

我发现这个问题的解决方案在于正确配置ConstructServicesUsing工厂方法.正如@Tseng指出的那样,使用该IServiceCollection.AddSingleton方法可以在ConfigureServicesStartup.cs 的方法中配置Automapper,这是应该完成的:

public void ConfigureServices(IServiceCollection services)
{
    //other service configuration omitted for simplicity

    //Automapper config
    services.AddSingleton(provider => AutoMapperConfig.Configure(provider));
}
Run Code Online (Sandbox Code Playgroud)

但至关重要的是,必须将Automapper配置为使用.NET Core的ActivatorUtilities类来创建服务实例(这篇文章归功于我的想法):

public static IMapperConfiguration Configure(IServiceProvider provider)
{
    var config = new MapperConfiguration(cfg => {
         cfg.AddProfile<MyProfile>();
         cfg.ConstructServicesUsing(type => ActivatorUtilities.CreateInstance(provider, type));
    });
    config.AssertConfigurationIsValid();
    return config;
}
Run Code Online (Sandbox Code Playgroud)

通过这种方法,Automapper配置为将任何服务依赖项注入自定义TypeConvertersValueResolvers.只需确保任何此类服务也添加到IServiceCollection实例中ConfigureServices.