Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dependency injection 在ASP.NET Core中向Autofac注册泛型类型时出现问题_Dependency Injection_Asp.net Core_Autofac - Fatal编程技术网

Dependency injection 在ASP.NET Core中向Autofac注册泛型类型时出现问题

Dependency injection 在ASP.NET Core中向Autofac注册泛型类型时出现问题,dependency-injection,asp.net-core,autofac,Dependency Injection,Asp.net Core,Autofac,我是Autofac和ASP.NET Core的新用户。我最近将一个小项目从“经典”ASP.NETWebAPI项目移植到ASP.NETCore。我在Autofac方面遇到了问题,特别是在注册泛型类型方面 这个项目使用一个命令模式,每个命令处理程序都是一个封闭的泛型 public class UpdateCustomerCommandHandler: ICommandHandler<UpdateCustomerCommand> 公共类UpdateCustomerCommandHandl

我是Autofac和ASP.NET Core的新用户。我最近将一个小项目从“经典”ASP.NETWebAPI项目移植到ASP.NETCore。我在Autofac方面遇到了问题,特别是在注册泛型类型方面

这个项目使用一个命令模式,每个命令处理程序都是一个封闭的泛型

public class UpdateCustomerCommandHandler: ICommandHandler<UpdateCustomerCommand>
公共类UpdateCustomerCommandHandler:ICommandHandler
这些命令处理程序被注入控制器中,如下所示:

readonly private ICommandHandler<UpdateCustomerCommand> _updateCustomerCommand;
public ValuesController(ICommandHandler<UpdateCustomerCommand> updateCustomerCommand)
{
    _updateCustomerCommand = updateCustomerCommand;
}
只读私有ICommandHandler\u updateCustomerCommand;
公共价值控制器(ICommandHandler updateCustomerCommand)
{
_updateCustomerCommand=updateCustomerCommand;
}
Autofac配置(部分)为:

var builder=newcontainerbuilder();
var assemblies=AppDomain.CurrentDomain.GetAssemblies();
//这似乎不像预期的那样有效。
builder.RegisterAssemblyTypes(程序集)
.As(t=>t.GetInterfaces()
。其中(a=>a.IsClosedTypeOf(typeof(ICommandHandler)))
.Select(a=>newkeyedservice(“commandHandler”,a));
上述情况似乎并没有像预期的那样注册泛型。如果我使用下面的注册方法,效果会很好

 builder.RegisterType<UpdateCustomerCommandHandler>().As<ICommandHandler<UpdateCustomerCommand>>();
builder.RegisterType().As();
当我说“它不工作”时,我的意思是,当尝试实例化控制器时,我得到“InvalidOperationException:无法解析类型'BusinessLogic.ICommandHandler`1[BusinessLogic.UpdateCustomerCommand]'的服务,同时尝试激活'AutoFac_Test.controller.ValuesController'

这在该项目的完整WebAPI版本中运行良好,但在ASP.NET Core中重新创建后效果不佳。要明确的是,在移植到ASP.NET内核之前,它工作得非常好

以下是我用来重新创建此问题的代码的链接:

****发现解决方案后编辑****


事实上,我的Autofac配置没有任何问题,当然Autofac本身也没有问题。发生的事情是,我重命名了依赖程序集的输出,以使程序集能够扫描(替换
AppDomain.CurrentDomain.GetAssemblies()
更优雅,但我从未修改API项目的依赖项以引用新程序集。因此,Autofac正在扫描正确加载的程序集,这些程序集恰好是较旧的版本,其中不包含我所期望的接口和实现…

Autofac内置了注册已关闭类型的o钢笔通用

builder
.RegisterAssemblyTypes(此程序集)
.AsClosedTypesOf(typeof(ICommandHandler));
这将扫描程序集,找到关闭打开的泛型接口的类型,并根据它们实现的关闭的泛型接口注册它们中的每一个-在您的例子中是,
ICommandHandler

在您的示例中,不起作用的是您将密钥与服务关联。Autofac在尝试实例化
ValuesController
时,不会查找您的
ICommandHandler
的密钥版本,这就是您得到异常的原因

在QuietEdition的评论后编辑:

我将尝试详细介绍键控与默认服务。您注册处理程序的方式是将
commandHandler
键与它们关联

这意味着,一旦构建了容器,以下是解析此类处理程序的唯一方法:

//容器将查找与“commandHandler”键关联的ICommandHandler的注册
container.resolvedkeyed(“commandHandler”);
在实例化
ValuesController
时,Autofac不会查找
ICommandHandler
的键控注册,因为它没有被要求这样做

它执行的等效代码是-您可以尝试自己运行该代码以获得异常:

//轰!
container.Resolve();
第二次注册有效的原因是您没有为服务设置密钥:

//没有密钥
建设者
.RegisterType()
.As();
//commandHandler键
建设者
.RegisterType()
.Keyed(“commandHandler”);
但是,由于您不想逐个注册所有处理程序,下面介绍如何在不键入它们的情况下注册它们:

builder
.RegisterAssemblyTypes(此程序集)
.AsClosedTypesOf(typeof(ICommandHandler));
/编辑

我可以看到两种情况,其中键控服务非常有用:

  • 您有几种类型实现相同的接口,并且希望在不同的服务中注入不同的实现。例如,您将
    SqlConnection
    DB2Connection
    注册为
    IDbConnection
    。然后您有两个服务,一个是针对SQL Server的,另一个是针对DB2的。如果两者都依赖于
    IDbConnection
    ,您需要确保在每个服务中注入正确的连接

  • 如果使用,注册的工作方式就是通过一个键定义decorator将应用到的服务——第一个示例是不言自明的


Autofac内置支持注册开放泛型的封闭类型

builder
.RegisterAssemblyTypes(此程序集)
.AsClosedTypesOf(typeof(ICommandHandler));
这将扫描程序集,找到关闭打开的泛型接口的类型,并根据它们实现的关闭的泛型接口注册它们中的每一个-在您的例子中是,
ICommandHandler

在您的示例中,不起作用的是您将密钥与服务关联。Autofac在尝试实例化
ValuesController
时,不会查找您的
ICommandHandler
的密钥版本,这就是您得到异常的原因

在QuietEdition的评论后编辑:

我将试着详细介绍一下键控与默认服务
 builder.RegisterType<UpdateCustomerCommandHandler>().As<ICommandHandler<UpdateCustomerCommand>>();
service.AddTransient(typeof(IThing<>), typeof(GenericThing<>));
service.AddTransient(typeof(GenericThing<>));
services.AddTransient(typeof(GenericThing<,>));