Dependency injection ASP.NET内核中的属性注入

Dependency injection ASP.NET内核中的属性注入,dependency-injection,asp.net-core,Dependency Injection,Asp.net Core,我正在尝试将ASP.NET应用程序移植到ASP.NET核心。我在我的UnitOfWork实现上有如下属性注入(使用Ninject): [注入] 公共IOrderRepository OrderRepository{get;set;} [注入] 公共ICCustomerRepository CustomerRepository{get;set;} 有没有一种方法可以使用.NET内核上的内置DI实现相同的功能?另外,是否可以使用基于约定的绑定?否,内置的DI/IoC容器在用法和功能上都有意保持简单

我正在尝试将ASP.NET应用程序移植到ASP.NET核心。我在我的UnitOfWork实现上有如下属性注入(使用Ninject):

[注入]
公共IOrderRepository OrderRepository{get;set;}
[注入]
公共ICCustomerRepository CustomerRepository{get;set;}

有没有一种方法可以使用.NET内核上的内置DI实现相同的功能?另外,是否可以使用基于约定的绑定?

否,内置的DI/IoC容器在用法和功能上都有意保持简单,以便为其他DI容器的插件提供基础

因此,没有内置的支持:自动发现、自动注册、装饰器或注入器,或基于约定的注册。据我所知,目前还没有计划将其添加到内置容器中

您必须使用具有属性注入支持的第三方容器

请注意,在98%的场景中,属性注入被认为是不好的,因为它隐藏了依赖项,并且不能保证在创建类时会注入对象

使用构造函数注入,您可以通过构造函数强制执行此操作,并检查null和不创建类实例。对于属性注入,这是不可能的,并且在单元测试期间,当类未在构造函数中定义时,类需要哪些服务/依赖项并不明显,因此很容易错过并获得
NullReferenceExceptions

我发现的唯一有效的属性注入原因是将服务注入到由第三方库生成的代理类中,即从您无法控制对象创建的接口创建的WCF代理。即使在那里,它也只适用于第三方库。如果您自己生成WCF代理,则可以通过
分部类
轻松扩展代理类,并添加新的DI友好构造函数、方法或属性

在任何地方都要避免它

有没有一种方法可以使用.NET内核上的内置DI实现相同的功能

没有,但以下是如何在的帮助下创建自己的
[inject]
属性

首先创建自己的
InjectAttribute

[AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=true)]
公共类InjectAttribute:属性
{
public InjectAttribute():base(){}
}
然后创建自己的
InjectPropertySelector
,它使用反射来检查标记为
[injecte]
的属性:

公共类InjectPropertySelector:DefaultPropertySelector
{
公共InjectPropertySelector(bool preserveSetValues):基(preserveSetValues)
{ }
公共重写bool InjectProperty(PropertyInfo PropertyInfo,对象实例)
{
var attr=propertyInfo.GetCustomAttribute(inherit:true);
return attr!=null&&propertyInfo.CanWrite
&&(!保留设置值)
||(propertyInfo.CanRead&&propertyInfo.GetValue(实例,null)==null));
}
}
然后在
ConfigureServices
您的
AutofacServiceProvider
中使用选择器:

公共类启动
{
公共IServiceProvider配置服务(IServiceCollection服务)
{
var builder=new ContainerBuilder();
建造商。填充(服务);
//使用属性选择器查找标记为[inject]的属性
builder.RegisterType();
this.ApplicationContainer=builder.Build();
返回新的AutofacServiceProvider(this.ApplicationContainer);
}
}
最后,在您的服务中,您现在可以使用
[inject]

公共类MyServiceX
{
[注入]
公共IOrderRepository OrderRepository{get;set;}
[注入]
公共ICCustomerRepository CustomerRepository{get;set;}
}
您当然可以进一步使用此解决方案,例如,通过使用属性来指定服务的生命周期,而不是服务的类定义

[可注入(LifetimeScope.SingleInstance)]
公共类存储库

…然后在通过Autofac配置服务时检查此属性。但这超出了本答案的范围。

它受支持。护士注射器:

您可以通过3个步骤完成:
  • 安装软件包
    DotNurse.Injector.AspNetCore
  • Program.cs调用以下方法
公共静态IHostBuilder CreateHostBuilder(字符串[]args)=>
Host.CreateDefaultBuilder(args)
.UseDotNurseInjector()//
{
webBuilder.UseStartup();
});
  • 然后可以使用[InjectService]属性而不是构造函数注入:
[InjectService]公共IBookRepository图书存储库{get;set;}

我不想争论,因为我是.NET核心的新手。 但是想象一下这样的情况:
class a
使用服务
Service1,…,Service5
,它们的接口
IService1,…,IService5
作为依赖项在其构造函数中传递<代码>类B继承自
类A
类C
继承自
类B
,等等。因此,所有这些派生类应至少通过其构造函数中的
IService1,…,IService5
接口。但是,
class B
及其派生的所有类都放在消费者库或应用程序中,因此
class A
开发人员无法访问

好的,现在
A类
的开发者会发现
A类
中包含的一些功能需要重构并外包到外部服务中,因为它需要在
A类
之外的其他地方使用。因此,它将其外包给
Service6
wi