在瞭解屬性注入以前,要先了解一下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使用 - 焰尾迭 - 博客園