ASP.NET Core 3.1 使用 Autofac 與註冊其他分層
Contents
ASP.NET Core 3.1 使用 Autofac 與註冊其他分層
步入ASP.NET Core 一定會遇到控制反轉(IoC)和相依性注入(DI)議題,ASP.NET Core有預設的DI Container 就是使用AddTransient
、AddScoped
、AddSingleton
,但若覺得內建的太簡易,可選擇第三方DI Container,最知名的選擇應該就是Autofac
,這邊簡單介紹一下Autofac基本導入,與幾種註冊其他分層方式
環境
- Nuget > Autofac.Extensions.DependencyInjection
架構
ASP.NET Core 3.1 預設 DI 用法
|
|
ASP.NET Core 3.1 導入 Autofac
-
安裝 Autofac.Extensions.DependencyInjection
-
在
Program.cs
加入服務1 2 3 4 5 6 7
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) // 這行 .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
-
在
Startup.cs
加入公開的ConfigureContainer()
方法,將要註冊的服務寫在裡面就完成了1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); } public void ConfigureContainer(ContainerBuilder builder) { // SingleInstance 相當於 AddSingleton // InstancePerLifetimeScope 相當於 AddScoped // InstancePerDependency 相當於 AddTransient builder.RegisterType<ProductRepository>().As<IProductRepository>().InstancePerLifetimeScope(); builder.RegisterType<ProductService>().As<IProductService>().InstancePerLifetimeScope(); builder.RegisterType<OrderRepository>().As<IOrderRepository>().InstancePerLifetimeScope(); builder.RegisterType<OrderService>().As<IOrderService>().InstancePerLifetimeScope(); builder.RegisterType<Sales>().As<IStatistics>().InstancePerLifetimeScope(); }
大量註冊
以上就是Autofac基本設置,接下來就是各種花式註冊,細節請自行參考 官方文件 ,因為用法很多,這邊純紀錄幾個自己用過的情況
-
直接註冊整個專案 或 註冊大量組件
使用 autofac,如果還一個一個註冊,那其實跟使用內建的沒有兩樣,通常同性質的如Repository層、Service層,結尾都會取相似名稱,這時可以大量註冊,這是我最常用的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
public void ConfigureContainer(ContainerBuilder builder) { // 註冊整個專案 var assemblysRepository = Assembly.Load("DataLayer"); builder.RegisterAssemblyTypes(assemblysRepository) .AsImplementedInterfaces() .InstancePerLifetimeScope(); var assemblysServices = Assembly.Load("ServiceLayer"); builder.RegisterAssemblyTypes(assemblysServices) .AsImplementedInterfaces() .InstancePerLifetimeScope(); // 專案內註冊大量相同結尾的檔案 //var assemblysRepository = Assembly.Load("DataLayer"); //builder.RegisterAssemblyTypes(assemblysRepository) // .Where(t => t.Name.EndsWith("Repository")) // .AsImplementedInterfaces() // .InstancePerLifetimeScope(); // 實作與介面不同專案 //Assembly Repository = Assembly.Load("Repository"); //Assembly IRepository = Assembly.Load("IRepository"); //builder.RegisterAssemblyTypes(Repository, IRepository) // .Where(t => t.Name.EndsWith("Repository")) // .AsImplementedInterfaces() // .InstancePerLifetimeScope(); }
-
將實作的控制交還各層
ServiceLayer、DataLayer 安裝 Aufofac ,新增一個類別繼承
Autofac.Module
類別,並且複寫Autofac.Module.Load
虛擬方法,範例如下1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class ServiceModules : Autofac.Module { protected override void Load(ContainerBuilder builder) { var dataAccess = Assembly.GetExecutingAssembly(); builder.RegisterAssemblyTypes(dataAccess) .Where(c => c.Name.EndsWith("Service")) .AsImplementedInterfaces(); // 讀取組件也可以這麼寫 //builder.RegisterAssemblyTypes( // GetType().GetTypeInfo().Assembly) // .Where(c => c.Name.EndsWith("Service")) // .AsImplementedInterfaces(); // 指定實作類別 builder.RegisterType<Sales>().As<IStatistics>().AsImplementedInterfaces(); } }
然後
ConfigureContainer
註冊這個類別1 2 3 4
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterModule(new ServiceModules()); }
好處是可以將實作類別控制權交由各層自行處理,壞處就是各層會增加了對 autofac 的依賴。
-
註冊DLL檔
註冊DLL檔,使用方法和上述是一樣的,先採用專案參考匯入要使用的服務,再設定即可
1 2 3 4 5 6 7 8 9 10
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterType<ClassA>().As<IShowClass>().InstancePerLifetimeScope(); // 註冊整個dll //var assemblysRepository = Assembly.Load("ClassLibrary1"); //builder.RegisterAssemblyTypes(assemblysRepository) // .AsImplementedInterfaces() // .InstancePerLifetimeScope(); }
參考
Autofac 官方文件