在了解属性注入以前,要先了解一下DI(Dependency Injection),即依赖注入。在ASP.NET Core里自带了一个IOC容器,并且程序支行也是基于这个容器创建起来的,在 Startup 里的 ConfigureService
方法里向容器注册服务类型。html
简单来讲,依赖注入就是容器帮咱们“new”一个对象,而且管理对象的生命周期。git
在依赖注入时,最经常使用的是构造方法注入。还有另外一种方法,那就是属性注入。github
在ASP.NET Core中,自带的容器是不支持属性注入的,可是能够经过替换容器来实现,也就是今天介绍的:经过 Autofac 来实现属性注入。web
Autofac 是一款超赞的.NET IoC 容器 . 它管理类之间的依赖关系, 从而使 应用在规模及复杂性增加的状况下依然能够轻易地修改 . 它的实现方式是将常规的.net类当作 组件 处理.框架
中文文档:https://autofaccn.readthedocs.io/zh/latest/ide
主要有如下三点:测试
一、引用类库ui
Autofac Autofac.Extensions.DependencyInjection
二、在 Program.cs
里替换系统默认容器编码
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) // 使用 autofac 的容器工厂替换系统默认的容器 .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
三、在 Startup.cs
的 ConfigureServices
里替换控制器的替换规则.net
public void ConfigureServices(IServiceCollection services) { // 替换控制器的替换规则 services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>()); // other configure services.AddControllers(); }
四、建立 AutowiredAttribute.cs
,用于标识使用属性注入
[AttributeUsage(AttributeTargets.Property)] public class AutowiredAttribute : Attribute { }
五、建立 AutofacModule.cs
,注册服务
/// <summary> /// 容器注册类 /// </summary> public class AutofacModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { // Register your own things directly with Autofac, like: builder.RegisterType<HelloService>().As<IHelloService>().InstancePerDependency().AsImplementedInterfaces(); // 获取全部控制器类型并使用属性注入 var controllerBaseType = typeof(ControllerBase); builder.RegisterAssemblyTypes(typeof(Program).Assembly) .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType) .PropertiesAutowired(new AutowiredPropertySelector()); } } /// <summary> /// 属性注入选择器 /// </summary> public class AutowiredPropertySelector : IPropertySelector { public bool InjectProperty(PropertyInfo propertyInfo, object instance) { // 带有 AutowiredAttribute 特性的属性会进行属性注入 return propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(AutowiredAttribute)); } }
六、在 Startup.cs
的 方法 ConfigureContainer
里注册上一步建立的 Module
类
// ConfigureContainer is where you can register things directly // with Autofac. This runs after ConfigureServices so the things // here will override registrations made in ConfigureServices. // Don't build the container; that gets done for you. If you // need a reference to the container, you need to use the // "Without ConfigureContainer" mechanism shown later. public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterModule(new AutofacModule()); }
示例代码下载:源码
[Autowired] private IHelloService HelloService { get; set; }
在控制器里添加服务属性,而后添加 [Autowired]
特性标识为属性注入便可。
属性注入很好用,可是要慎重使用,由于属性注入会形成类型的依赖关系隐藏,测试不友好等。
建议:在封闭框架时可使用,但不能大范围使用,只有必须使用属性注入来达到效果的地方才会使用,用来提升使用框架时的编码效率,来达到一些便利,脱离框架层面,编写业务代码时,不得使用。
主要参考文章:
使用 autofac 实现 asp .net core 的属性注入
ASP.NETCore 3.0 Autofac替换及控制器属性注入及全局容器使用 - 情·深 - 博客园
autofac 的官方示例:
autofac/Examples: Example projects that consume and demonstrate Autofac IoC functionality and integration
autofac 文档:
Welcome to Autofac’s documentation! — Autofac 5.2.0 documentation
欢迎来到 Autofac 中文文档! — Autofac 4.0 文档
其它:
ASP.NET Core 奇淫技巧之伪属性注入 - 晓晨Master - 博客园
.net core2.0下Ioc容器Autofac使用 - 焰尾迭 - 博客园