1. 程式人生 > >ASP.NET CORE依賴註入&AutoFac

ASP.NET CORE依賴註入&AutoFac

project eof 簡潔 重新 每次 imp sum unity builder

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