ASP.NET Core 通过属性注入依赖
- 我们不做容器,我们只是
NET Core Container
的搬运工(在默认容器的基础上增加了一些功能)。 - 不要在构造函数中使用
NAutowired
。 - 由于我们与那些
妖艳的
第三方IoC Container
有些不同,我们没有替换NetCore
默认的Container
,这意味着您依然可以在Startup
里使用IServiceCollection
将服务加入到Container
并使用NAutowired
还原这些依赖。 - 虽然有人觉得Spring风格的DI有点反模式(显式依赖),但是写起来爽。
nuget
包管理器中引入NAutowired
和NAutowired.Core
。NAutowired
包应该只在Web或Console项目中被引用,NAutowired.Core
包则在需要添加特性的项目中被引用。
默认情况下,ASP.NET Core
生成Controller
时从容器中解析Controller
构造函数中的依赖,但是不从容器中还原控制器,这导致:
Controller
的生命周期由框架处理,而不是请求的生命周期Controller
构造函数中参数的生命周期由请求生命周期处理- 在
Controller
中通过属性注入
将不起作用
您必须使用AddControllersAsServices
方法,将Controller
注册为Service
,以便Controller
在还原时使用属性注入
。
public void ConfigureServices(IServiceCollection services) {
//register controllers as services
services.AddControllers().AddControllersAsServices();
//replace `IControllerActivator` implement.
services.Replace(ServiceDescriptor.Transient<IControllerActivator, NAutowiredControllerActivator>());
}
public class Startup {
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//将FooService加到容器
services.AddScoped<FooService>();
}
}
[Route("api/[controller]")]
[ApiController]
public class FooController : ControllerBase {
//使用Autowired Attribute注入实例
[Autowired]
private readonly FooService fooService;
[HttpGet]
public ActionResult<string> Get() {
return fooService == null ? "failure" : "success";
}
}
public class Startup {
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//将Filter加到容器
services.AddScoped<AuthorizationFilter>();
}
}
//使用 ServiceFilterAttribute
[NAutowired.Attributes.ServiceFilter(typeof(AuthorizationFilter))]
public class FooController : ControllerBase {
}
public class AuthorizationFilter : IAuthorizationFilter {
[Autowired]
private readonly FooService fooService;
public void OnAuthorization(AuthorizationFilterContext context) {
System.Console.WriteLine($"{fooService.ToString()} in filter");
return;
}
}
public class Startup : NAutowired.Core.Startup
{
[Autowired]
private readonly FooService fooService;
//程序启动时将会执行此方法
public override void Run(string[] args)
{
System.Console.WriteLine(fooService.Foo());
System.Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
ConsoleHost.CreateDefaultBuilder(new List<string> { "assemblyName" }, args).Build().Run<Startup>();
//你也可以让NAutowired使用你传递的IServiceCollection
/*
ConsoleHost.CreateDefaultBuilder(() => {
var serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddTransient<FooService>();
return serviceDescriptors;
}, new List<string> { "NAutowiredConsoleSample" }, args).Build().Run<Startup>();
*/
}
}
[Route("api/[controller]")]
[ApiController]
public class FooController : ControllerBase {
//注入特定的实例
[Autowired(typeof(FooService))]
private readonly IService service;
[HttpGet]
public ActionResult<string> Get() {
return service == null ? "failure" : "success";
}
}
public class Startup {
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//使用自动注入
services.AutoRegisterDependency(new List<string> { "NAutowiredSample" });
}
}
//默认Lifetime值为Scoped
[Service]
//Lifetime可供选择依赖注入的生命周期
//[Service(Lifetime.Singleton)]
public class FooService {
}
[Service(implementInterface: typeof(IService))]
//注入特定的实现类到容器。这将执行services.AddScoped(typeof(IService), typeof(FooService));
public class FooService: IService {
}
NAutowired
会自动扫描AutoRegisterDependency(assemblyNames)
方法配置的程序集下的所有类,并将具有[Service] [Repository] [Component] [ServiceFilter]
特性的类注入到容器。