一. 配置的讀取
在Asp.Net Core中,有一個 appsettings.json 文件,用於存儲相應的配置信息,讀取的時,要通過構造函數注入:IConfiguration Configuration,來進行讀取。
下面是一段配置文件,我們來對其進行讀取:
讀取代碼:
1 public IConfiguration Configuration { get; } 2 public FirstController(IConfiguration configuration) 3 { 4 Configuration = configuration; 5 } 6 { 7 var f0 = Configuration["MyFullName"]; 8 var f1 = Configuration["User:userName"]; 9 var f2 = Configuration["User:Child:childName"]; 10 var f3 = Configuration["StudentList:0:sName"]; 11 var f4 = Configuration["StudentList:1:sName"]; 12 }
二. StartUp類
1. 說明:
StartUp類中包括兩個方法,分別是ConfigureServices和Configure,前者主要用來注冊服務,后者主要用來創建和配置請 求管道,然后在Main方法中進行調用:
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>();
2. ConfigureServices方法
(1). 它在Configure方法調用之前,由主機調用。
(2). 需要大量設置的功能,IServiceCollection 上有 Add{Service} 擴展方法,常見的如下:
a:services.AddDbContext<ApplicationDbContext>(options =>options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection")));
b:services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap4).AddEntityFrameworkStores<ApplicationDbContext>();
c:services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
3. Configure方法
(1).用於配置Http請求管道,主要通過IApplicationBuilder實例來配置。
(2).常見的管道有:
開發人員異常頁(UseDeveloperExceptionPage)、
HTTP嚴格傳輸安全性(UseHsts)、
HTTPS重定向(UseHttpsRedirection)、
靜態文件(UseStaticFiles)、
MVC(UseMvc)。
三. 內置依賴注入和擴展改造
1. 說明:
這里不再介紹什么是IOC和DI,直接介紹內置依賴注入的使用方法和生命周期,最后介紹利用AutoFac進行替換內置IOC容器。事先准備好U1-U4四個類和IU1-IU4四個接口。
接口和類的代碼:

1 public interface IU1 2 { 3 string guid { get; set; } 4 string GetName(); 5 } 6 public interface IU2 7 { 8 string guid { get; set; } 9 string GetName(); 10 } 11 public interface IU3 12 { 13 string guid { get; set; } 14 string GetName(); 15 } 16 public interface IU4 17 { 18 string guid { get; set; } 19 string GetName(); 20 }

1 public class U1 : IU1 2 { 3 public string guid { get; set; } 4 5 public U1() 6 { 7 guid = System.Guid.NewGuid().ToString("N"); 8 } 9 10 /// <summary> 11 /// 調用方法的時候,是單例也沒有用,每次調用都會變 12 /// </summary> 13 /// <returns></returns> 14 public string GetName() 15 { 16 return System.Guid.NewGuid().ToString("N"); 17 } 18 } 19 public class U2 : IU2 20 { 21 public string guid { get; set; } 22 23 public U2() 24 { 25 guid = System.Guid.NewGuid().ToString("N"); 26 } 27 28 /// <summary> 29 /// 調用方法的時候,是單例也沒有用,每次調用都會變 30 /// </summary> 31 /// <returns></returns> 32 public string GetName() 33 { 34 return System.Guid.NewGuid().ToString("N"); 35 } 36 } 37 public class U3 : IU3 38 { 39 public string guid { get; set; } 40 41 public U3() 42 { 43 guid = System.Guid.NewGuid().ToString("N"); 44 } 45 46 /// <summary> 47 /// 調用方法的時候,是單例也沒有用,每次調用都會變 48 /// </summary> 49 /// <returns></returns> 50 public string GetName() 51 { 52 return System.Guid.NewGuid().ToString("N"); 53 } 54 } 55 public class U4 : IU4 56 { 57 public string guid { get; set; } 58 59 public U4() 60 { 61 guid = System.Guid.NewGuid().ToString("N"); 62 } 63 64 /// <summary> 65 /// 調用方法的時候,是單例也沒有用,每次調用都會變 66 /// </summary> 67 /// <returns></returns> 68 public string GetName() 69 { 70 return System.Guid.NewGuid().ToString("N"); 71 } 72 }
2. 核心:
利用IServiceCollection services這個對象進行注冊,而這個對象在Startup類中的ConfigureServices中已經注入進去了, 也就是說我在自定義對象的注冊是的時候,可以直接在ConfigureServices類中進行注冊,然后在控制器中使用的時候通過構造函數進行注入即可。
PS:我們也可以自己 IServiceCollection container = new ServiceCollection(); 然后進行注冊(不推薦,特殊情況下可能這么用)
3. 生命周期分為三種:
瞬時的(AddTransient)、請求內單例(AddScoped)、單例(AddSingleton 兩種寫法)。
4. 測試:
兩次訪問該頁面,發現ViewBag.r1 和 ViewBag.r2兩次的值不同,ViewBag.r3和ViewBag.r4兩次的值相同。
代碼分享:
1 public void ConfigureServices(IServiceCollection services) 2 { 3 services.Configure<CookiePolicyOptions>(options => 4 { 5 // This lambda determines whether user consent for non-essential cookies is needed for a given request. 6 options.CheckConsentNeeded = context => true; 7 options.MinimumSameSitePolicy = SameSiteMode.None; 8 }); 9 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); 10 11 //自定義注冊對象 12 { 13 services.AddTransient<IU1, U1>(); //瞬時的 14 services.AddScoped<IU2, U2>(); //一次請求內是不變的 15 services.AddSingleton<IU3, U3>(); //單例的 16 services.AddSingleton<IU4>(new U4()); //單例的 17 18 } 19 }
1 public class FirstController : Controller 2 { 3 public IU1 U1 { get; } 4 public IU1 U11 { get; } 5 public IU2 U2 { get; } 6 public IU2 U22 { get; } 7 public IU3 U3 { get; } 8 public IU3 U33 { get; } 9 public IU4 U4 { get; } 10 public IU4 U44 { get; } 11 12 public FirstController(IU1 u1, IU1 u11, IU2 u2, IU2 u22, IU3 u3, IU3 u33, IU4 u4, IU4 u44) 13 { 14 U1 = u1; 15 U11 = u11; 16 U2 = u2; 17 U22 = u22; 18 U3 = u3; 19 U33 = u33; 20 U4 = u4; 21 U44 = u44; 22 } 23 24 public IActionResult Index() 25 { 26 bool a = object.ReferenceEquals(U1, U11); 27 bool b = object.ReferenceEquals(U2, U22); 28 bool c = object.ReferenceEquals(U3, U33); 29 bool d = object.ReferenceEquals(U4, U44); 30 31 //分兩次請求來查看 32 ViewBag.r1 = U1.guid; 33 ViewBag.r2 = U2.guid; 34 ViewBag.r3 = U3.guid; 35 ViewBag.r4 = U4.guid; 36 37 //下面是自己創建的的模式進行訪問 38 { 39 IServiceCollection container = new ServiceCollection(); 40 container.AddTransient<IU2, U2>(); 41 //要放在注冊的后面 42 var provider = container.BuildServiceProvider(); 43 IU2 user1 = provider.GetService<IU2>(); 44 IU2 user2 = provider.GetService<IU2>(); 45 bool cc = object.ReferenceEquals(user1, user2);47 } 48 return View(); 49 } 50 }
1 <div class="text-center"> 2 <h1 class="display-4">Welcome</h1> 3 <p>瞬時的:@ViewBag.r1</p> 4 <p>請求內單例:@ViewBag.r2</p> 5 <p>全局單例寫法1:@ViewBag.r3</p> 6 <p>全局單例寫法2:@ViewBag.r4</p> 7 </div>
補充:
如果不想通過構造函數注入,則可以通過[FromServices]特性來給某個特定方法注入:
如: public void Test(【FromServices】IU1 u1){ }。
兩次訪問的請求結果
5. 為什么要用AutoFac進行替換內置容器?
因為某些特定的功能內置的容器不支持,比如:屬性的注入、基於名稱的注入、子容器、自定生存期管理、對遲緩初始化的 Func<T> 支持
6. 用AutoFac替換的步驟
(1). 通過Nuget安裝AutoFac【4.9.2】和Autofac.Extensions.DependencyInjection【4.4.0】
(2). 改造ConfigureServices中配置容器並返回IServiceProvider,配置代碼詳見具體類,注入的代碼封裝到DefaultModule。
1 public IServiceProvider ConfigureServices(IServiceCollection services) 2 { 3 services.Configure<CookiePolicyOptions>(options => 4 { 5 // This lambda determines whether user consent for non-essential cookies is needed for a given request. 6 options.CheckConsentNeeded = context => true; 7 options.MinimumSameSitePolicy = SameSiteMode.None; 8 }); 9 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); 10 11 // Add Autofac 12 var containerBuilder = new ContainerBuilder(); 13 containerBuilder.RegisterModule<DefaultModule>(); 14 containerBuilder.Populate(services); 15 var container = containerBuilder.Build(); 16 return new AutofacServiceProvider(container); 17 }
DefaultModule代碼分享
特別注意:AutoFac的生命周期也有:瞬時的、單次請求內單例的、全局單例的。
1 public class DefaultModule: Module 2 { 3 protected override void Load(ContainerBuilder builder) 4 { 5 //這里就是AutoFac的注入方式,下面采用常規的方式 6 //詳見:https://www.cnblogs.com/yaopengfei/p/9479268.html 7 //官網:https://autofac.org/ 8 9 //特別注意:其中很大的一個變化在於,Autofac 原來的一個生命周期InstancePerRequest,將不再有效。正如我們前面所說的,整個request的生命周期被ASP.NET Core管理了, 10 //所以Autofac的這個將不再有效。我們可以使用 InstancePerLifetimeScope ,同樣是有用的,對應了我們ASP.NET Core DI 里面的Scoped。 11 12 //瞬時請求(省略InstancePerDependency 也為瞬時) 13 builder.RegisterType<U1>().As<IU1>().InstancePerDependency(); 14 //單次請求內單例 15 builder.RegisterType<U2>().As<IU2>().InstancePerLifetimeScope(); 16 //全局單例 17 builder.RegisterType<U3>().As<IU3>().SingleInstance(); 18 builder.RegisterType<U4>().As<IU4>().SingleInstance(); 19 20 } 21 }
(3). 其他都不變,可以繼續沿用構造函數注入。
參考文章:
https://www.cnblogs.com/yaopengfei/p/9479268.html (.Net 平台下的AutoFac的用法)
https://www.cnblogs.com/jesse2013/p/di-in-aspnetcore.html
!
- 作 者 : Yaopengfei(姚鵬飛)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 聲 明1 : 本人才疏學淺,用郭德綱的話說“我是一個小學生”,如有錯誤,歡迎討論,請勿謾罵^_^。
- 聲 明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。