ASP.NET Core 3.1默認DI使用以及使用autofac注入


在ASP.NET Core中,自帶的IOC容器相關的使用方式和注入類型的生命周期.

.netcore內置依賴注入,通過services.AddTransient、services.AddScoped、services.AddSingleton這些方法即可實現構造函數注入。

微軟給自行注入的服務,提供了3種生命周期.

Transient(瞬時的)

 每次請求時都會創建的瞬時生命周期服務。這個生命周期最適合輕量級,無狀態的服務。

Scoped(作用域的)

在同作用域,服務每個請求只創建一次。

Singleton(唯一的)

全局只創建一次,第一次被請求的時候被創建,然后就一直使用這一個.

如何使用這三種生命周期呢?.我們直接在注入的時候用不同的方法就行了,代碼如下:

//注冊不同生命周期的服務
services.AddTransient<ITestService, TestService>(); services.AddScoped<ITestService2, TestService2>(); services.AddSingleton<ITestService3, TestService3>();  

自帶的IOC 做一些小的項目完全沒有問題,但是大項目使用起來就比較單一,所以我們將默認的IOC容器替換為Autofac

Autofac可完美替換系統的依賴注入功能,可實現構造函數注入和屬性注入,替換過程:

在Program.cs 新增一行代碼

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())//集成Autofac
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });

然后在Startup.cs 增加方法

         //集成Autofac
         public void ConfigureContainer(ContainerBuilder builder)
         {
             //添加依賴注入實例,AutofacModuleRegister就繼承自Autofac.Module的類
             builder.RegisterModule(new StartupHelp.AutofacModuleRegister());
         }

ConfigureAutofac 是自己封裝的一個類  繼承了 Autofac.Module

其中注冊類必須繼承自Autofac.Module,並且在Load中實現注入,此處應用了程序集范圍的注入以及單個對象的注入,最后添加的代碼是為了支持控制器的屬性注入。

注入的接口(如IUnitOfWork)和實現(UnitOfWork)沒有特別。

注入對象的生命周期與.netcore內置的一致

public class AutofacRegister : Autofac.Module
    {
        #region 單個類和接口
        //直接注冊某一個類和接口
        //左邊的是實現類,右邊的As是接口
        //containerBuilder.RegisterType<TestServiceE>().As<ITestServiceE>().SingleInstance();
        //這里就跟默認DI差不多
        //services.AddScoped<TestServiceE, ITestServiceE>();
        #endregion

        #region 方法1   Load 適用於無接口注入
        //var assemblysServices = Assembly.Load("Exercise.Services");

        //containerBuilder.RegisterAssemblyTypes(assemblysServices)
        //          .AsImplementedInterfaces()
        //          .InstancePerLifetimeScope();

        //var assemblysRepository = Assembly.Load("Exercise.Repository");

        //containerBuilder.RegisterAssemblyTypes(assemblysRepository)
        //          .AsImplementedInterfaces()
        //          .InstancePerLifetimeScope();

        #endregion

        #region 方法2  選擇性注入 與方法1 一樣
        //            Assembly Repository = Assembly.Load("Exercise.Repository");
        //            Assembly IRepository = Assembly.Load("Exercise.IRepository");
        //            containerBuilder.RegisterAssemblyTypes(Repository, IRepository)
        //.Where(t => t.Name.EndsWith("Repository"))
        //.AsImplementedInterfaces().PropertiesAutowired();

        //            Assembly service = Assembly.Load("Exercise.Services");
        //            Assembly Iservice = Assembly.Load("Exercise.IServices");
        //            containerBuilder.RegisterAssemblyTypes(service, Iservice)
        //.Where(t => t.Name.EndsWith("Service"))
        //.AsImplementedInterfaces().PropertiesAutowired();
        #endregion

        #region 方法3  使用 LoadFile 加載服務層的程序集  將程序集生成到bin目錄 實現解耦 不需要引用
        //獲取項目路徑
        //var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
        //var ServicesDllFile = Path.Combine(basePath, "Exercise.Services.dll");//獲取注入項目絕對路徑
        //var assemblysServices = Assembly.LoadFile(ServicesDllFile);//直接采用加載文件的方法
        //containerBuilder.RegisterAssemblyTypes(assemblysServices).AsImplementedInterfaces();

        //var RepositoryDllFile = Path.Combine(basePath, "Exercise.Repository.dll");
        //var RepositoryServices = Assembly.LoadFile(RepositoryDllFile);//直接采用加載文件的方法
        //containerBuilder.RegisterAssemblyTypes(RepositoryServices).AsImplementedInterfaces();
        #endregion

        #region 在控制器中使用屬性依賴注入,其中注入屬性必須標注為public
        //public ITestServiceE _testService {get;set }
        //注意 上方為屬性注入  發現為Null  需要在Startup.cs  的 ConfigureServices 方法下加入如下代碼
        //services.AddControllers().AddControllersAsServices();

        //在控制器中使用屬性依賴注入,其中注入屬性必須標注為public
        //        var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
        //.Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type)).ToArray();
        //        containerBuilder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
        #endregion

        /// <summary>
        /// 當前使用
        /// </summary>
        /// <param name="builder"></param>
        protected override void Load(ContainerBuilder builder)
        {
            //程序集范圍注入 將匹配所有Service結尾的
            builder.RegisterAssemblyTypes(typeof(SysUserService).Assembly)
                 .Where(t => t.Name.EndsWith("Service"))
                 .AsImplementedInterfaces().PropertiesAutowired();
            //單個注冊 工作單元 和數據庫上下文
            builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().PropertiesAutowired();
            builder.RegisterType<dbContext>().As<DbContext>().PropertiesAutowired();

            //在控制器中使用屬性依賴注入,其中注入屬性必須標注為public  就是不需要通過構造函數 直接
            //public ITestServiceE _testService {get;set }   可直接_testService.方法  不許在構造函數接收
            //注意屬性注入 發現為Null  需要在Startup.cs  的 ConfigureServices 方法下加入如下代碼
            //services.AddControllers().AddControllersAsServices();
            var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
            .Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type)).ToArray();
            builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
        }
    }

然后控制器通過構造函數注入,或者屬性注入測試

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM