Dependency injection 将依赖项注入ASP.NET内核中的Automapper TypeConverter

Dependency injection 将依赖项注入ASP.NET内核中的Automapper TypeConverter,dependency-injection,asp.net-core,automapper,Dependency Injection,Asp.net Core,Automapper,要获得DI框架以将依赖项注入Automapper自定义类型转换器,通常使用MapperConfiguration对象的ConstructServicesUsing方法。因此,使用ASP.NET Core DI,我希望能够如下配置AutoMapper: public static IMapperConfiguration Configure(IServiceProvider provider) { var config = new MapperConfiguration(cfg =>

要获得DI框架以将依赖项注入Automapper自定义类型转换器,通常使用
MapperConfiguration
对象的
ConstructServicesUsing
方法。因此,使用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;
}
依赖项(在本例中是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
    }
}
公共类MyConverter:ITypeConverter
{
专用图像映射器;
公共MyConverter(IMapperConfiguration mapperConfig)
{
var mc=mapperConfig作为MapperConfiguration;
_mapper=mc.CreateMapper();
}
公共类型转换(ResolutionContext上下文)
{
//在这里用_mapper做点什么
}
}
我已经在几个DI框架中成功地使用了这个模式,但是我无法让它与ASP.NET核心一起工作。猜测一下,我认为Automapper可能需要获得真正的IServiceProvider实例,该实例是在ConfigureServices方法完成后由.NET构建的。然而,即使我将该部分配置推迟到Configure方法(见下文)时,依赖项仍然不会被注入到TypeConverter中

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider provider)
{
    var config = provider.GetService<IMapperConfiguration>();
    config.ConstructServicesUsing(type => provider.GetService(type));
}
public void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂、IServiceProvider提供程序)
{
var config=provider.GetService();
config.ConstructServicesUsing(type=>provider.GetService(type));
}

因此,我的问题是:如何使用ASP.NET核心配置Automapper,以便它将依赖项注入自定义类型转换器?

您可以/应该使用工厂方法注入/实例化服务

services.AddSingleton((serviceProvider)=>AutoMapperConfig.Configure(serviceProvider));
这样,您可以延迟对
Configure
的调用,直到第一次解决
IMapperConfiguration
为止。由于它是单例的,它将在应用程序容器的其余部分保持活动状态,对
RequestService
的进一步调用将返回相同的实例

编辑:

尝试删除
config.assertconfigurationsvalid()
AutoMapperConfig.Configure
方法,并在
Startup.cs

public void配置(IServiceProvider应用程序)
{
app.VerifyAutoMapperConfig();
}
AutoMapperConfigExtensions.cs

//因此不必添加名称空间即可使用
//在Startup.cs内部;建议所有中间件注册它们的
//AddXxx和UseXxx扩展方法
命名空间Microsoft.Extensions.DependencyInjection{
公共静态类自动映射配置扩展
{
public static void VerifyAutoMapperConfig(此IServiceProvider应用程序)
{
var config=app.RequestService();
config.assertconfigurationsvalid();
}
}
}

我发现解决此问题的方法在于使用工厂方法正确配置
构造服务。正如@Tseng所指出的,使用
IServiceCollection.AddSingleton
方法可以在Startup.cs的
ConfigureServices
方法中配置Automapper,这是应该完成的:

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

    //Automapper config
    services.AddSingleton(provider => AutoMapperConfig.Configure(provider));
}
但至关重要的是,Automapper必须配置为使用.NET Core的
ActivatorUtilities
类来创建服务实例(感谢您给了我这个想法):

publicstaticimapperconfiguration配置(IServiceProvider提供程序)
{
var config=new-MapperConfiguration(cfg=>{
AddProfile();
ConstructServicesUsing(type=>ActivatorUtilities.CreateInstance(provider,type));
});
config.assertconfigurationsvalid();
返回配置;
}

通过这种方法,Automapper被配置为将任何服务依赖项注入到定制的
TypeConverters
ValueResolver
中。只需确保在
ConfigureServices

中的
IServiceCollection
实例中也添加了任何此类服务,您是否仍在使用ASP.NET 5 beta7或beta8?我记得
services.AddInstance
被重命名为
AddSingleton
以保持它与其他singleton注册保持一致我的错,它出现在RC2的公告中,但它是很久以前的事了,我以为它是在RC1发布之前。无论如何,我都在使用RC1。谢谢,这看起来很有希望。然而,不幸的是,我在尝试使用TypeConverter时遇到了相同的错误:
MyConverter需要一个具有0个参数或仅可选参数的构造函数\r\n参数名称:type
。我想知道AM 4.2是否在使用IServiceProvider引用来注入依赖项,就像在以前的版本中一样。我怀疑您在这里有一个循环依赖项。您的
MyConverter
依赖于
IMapperConfiguration
,但是
IMapperConfiguration
只能在调用
AutoMapperConfig.Configure
后解析,但因为您调用的是
config.assertconfigurationsvalid()在configure中,它会在返回之前尝试解析它。尝试将此调用移到Configure方法之外,即Startup.cs的
Configure(IServiceProvider应用程序)
方法内部。我将用一个例子更新答案不幸的是,这也不能解决它。顺便说一句,当我调试代码时,我可以看到AutomapperConfig.Configure方法直接从服务配置中调用,并添加到Startup.cs中。正如你所说,它不会推迟到第一次使用。这让我想知道我是否在某个地方做错了什么。此外,我尝试用另一个可注入服务替换
MyConverter
IMapperConfiguration
依赖项,但得到了相同的错误,因此我想这排除了循环依赖项问题。在被调用时是
provider.GetService(type)
public void ConfigureServices(IServiceCollection services)
{
    //other service configuration omitted for simplicity

    //Automapper config
    services.AddSingleton(provider => AutoMapperConfig.Configure(provider));
}
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;
}