ASP.NET CORE依賴註入&AutoFac
1. 前言
關於IOC模式和DI技術,網上已經有很多相關的探討,再次就不過多贅述了,只是簡單介紹一下它們的概念
- 控制反轉(IoC/Inverse Of Control): 調用者將創建實例的控制權交給IOC容器,由容器創建,所以稱為控制反轉。
- 依賴註入(DI/Dependence injection) : 容器創建好實例後再註入給調用者的過程稱為依賴註入。依賴註入技術讓我們的應用程序實現了松散耦合
.NetFramewok和.Net Core的區別之一就是.net core所有的實例都是通過依賴註入來創建的。下面介紹一下ASP.NET CORE中如何使用依賴註入
2.ASP.NET Core 中自帶的DI方式
ASP.NET Core本身已經集成了一個輕量級的IOC容器,開發者只需要定義好接口後,在Startup.cs的ConfigureServices方法裏使用對應生命周期的綁定方法即可
例:
//註冊數據庫基礎操作 services.AddScoped(typeof(IBLLConstruct<>), typeof(BLLConstruct<>)); //註冊緩存操作 services.AddTransient(typeof(ICacheContext), typeof(CacheContext)); services.AddScoped(typeof(IAuth), typeof(LocalAuth)); services.AddSingleton(typeof(IHttpContextAccessor), typeof(HttpContextAccessor));
AddTransient:服務在每次請求時被創建
AddScoped:服務在每次請求時被創建,生命周期橫貫整次請求
AddSingleton:顧名思義Singleton(單例),服務在第一次請求時被創建(或者當我們在ConfigureServices中指定創建某一實例並運行方法),其後的每次請求將沿用已創建服務
在這之後,我們便可以將服務通過構造函數註入或者是屬性註入的方式註入到Controller,View(通過使用@inject
),甚至是Filter中(以前的項目是使用Unity將依賴註入到Filter,個人感覺不如.net core中註入的簡潔)。
3.構造函數獲取實例
//數據訪問 protected IBLLConstruct<UserInforMations> _repository { get; set; } //緩存 protected ICacheContext _cache { get; set; } protected IAuth _auth { get; set; } public LoginService(IBLLConstruct<UserInforMations> repository, ICacheContext cache, IAuth auth) { this._cache = cache; this._repository = repository; this._auth = auth; }
流程大概就是這樣,我們啟動項目來看一下它的執行順序
(1)容器創建實例
(2)構造函數獲取實例
4.使用AutoFac實現擴展
除了ASP.NETCore自帶的IOC容器外,我們還可以使用其他成熟的DI框架,如Autofac,StructureMap等(本人只用過Unity,Autofac)。
(1)安裝autofac
(2)創建容器並註冊依賴
修改Startup.cs中ConfigureServices方法 不要忘了將ConfigureServices的返回值修改為IServiceProvider
public IServiceProvider ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddDbContext<DirectSellContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DBContext"), b => b.UseRowNumberForPaging())); //使用AutoFac進行註入 return new AutofacServiceProvider(AutofacExt.InitAutofac(services)); }
(3)在AutofacExt類中創建容器並註冊依賴
private static IContainer _container; public static IContainer InitAutofac(IServiceCollection services) { var builder = new ContainerBuilder(); builder.RegisterType<GuidTransientAppService>().As<IGuidTransientAppService>(); builder.RegisterType<GuidScopedAppService>().As<IGuidScopedAppService>().InstancePerLifetimeScope(); builder.RegisterType<GuidSingletonAppService>().As<IGuidSingletonAppService>().SingleInstance(); builder.Populate(services); _container = builder.Build(); return _container; }
InstancePerLifetimeScope:同一個Lifetime生成的對象是同一個實例
SingleInstance:單例模式,每次調用,都會使用同一個實例化的對象;每次都用同一個對象;
InstancePerDependency:默認模式,每次調用,都會重新實例化對象;每次請求都創建一個新的對象;
(4)AutoFac批量註冊服務
通過以上方式可以實現註入,但是我們每定義一個接口,都要在AutoFac中註冊一次,可以使用RegisterAssemblyTypes來避免這種重復勞動
反射獲取程序集
/// <summary> /// 根據程序集名稱獲取程序集 /// </summary> /// <param name="AssemblyName">程序集名稱</param> /// <returns></returns> public static Assembly GetAssemblyByName(String AssemblyName) { return Assembly.Load(AssemblyName); }
批量註冊
//註冊Service中的對象,Service中的類要以Service結尾,否則註冊失敗 builder.RegisterAssemblyTypes(GetAssemblyByName("MyProject.Domain")). Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces();
這樣就實現了Domain層中以Service結尾的接口批量註冊 命名格式如下:
ASP.NET CORE依賴註入&AutoFac