.NET與.NETCore
在5.0版本之前,.NET代表.NETFramework,在5.O版本之后Framework被拋棄,與Core合並為.NET5.0
.NETCore從哪開始
毫無疑問,C#程序都是以Program.cs文件中的Main方法開始。
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
可以看到,程序先創建了個IHostBuilder,將args參數傳入Host.CreateDefaultBuilder
方法中。在此方法中才調用大名鼎鼎的Startup類。
可以不使用Startup類,其作用只是配置host,甚至可以根據控制台指令執行不同的TStartup類。
自定義TStartup:(TStartup可以是任意類,沒有接口限制。)
public class ClassOne
{
public ClassOne(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
var conn = Configuration["ConnectionString:DefaultConn"];
services.AddDbContext<ApplicationDbContext>(option => option.UseSqlServer(conn));
services.AddIdentity<Useraccount, IdentityRole>(
options => options.SignIn.RequireConfirmedAccount = true
).AddEntityFrameworkStores<ApplicationDbContext>();
services.AddControllersWithViews(
config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
}
);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
必須要的幾點:
1.帶IConfiguration
參數的構造函數。
2.public IConfiguration Configuration { get; }
3.public void ConfigureServices(IServiceCollection services)
因為要使用MVC必須先注冊服務。
4.public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
參數自己看着加,IApplicationBuilder是設置中間件,IWebHostEnvironment是文件環境(可以取根目錄等等)。
服務的依賴注入
依賴注入DI和控制反轉IoC
-
依賴注入
首先理解依賴:public class MyClass { List<int> _list; public void Change() { _list.Count; } }
在MyClass中有一個_list屬性,就說明其存在一個依賴。並且可以發現_list沒有初始化,並且Change方法希望訪問其Count參數。按上述代碼是不會編譯通過的。所以需要從外部注入_list實例。這就是依賴注入的含義。
public class MyClass
{
List<int> _list;
public void Change(List<int> list)
{
_list.Count;
}
}
-
控制反轉
學習了接口之后,我們得以充分了解面向對象的特點——多態。多態的特性是實現控制反轉的基礎。在沒有多態之前,每個函數都必須接受精確的、數量相同的參數。這說明控制權掌握在函數。將參數類型調整為基類(如Object)時,函數可接受范圍變大,函數是處於被動接受的狀態——給什么參數都要收。這就叫控制反轉。
但是有時候會發現使用Object太廣泛了,所以接口的作用就凸顯出來了。在C#中,接口就是對類的特點的集合。例如有許許多多不同種類的鳥,但是他們都有共同的特點——會飛、長有兩只翅膀。那么就可以使用IBird接口抽象形容它。使用接口做參數相對於用Object同樣是控制反轉,只是范圍縮小了。public class MyClass { IList<int> _list; public void Change(IList<int> list) { _list.Count; } }
回到Core中
services.AddScoped<IAccountProfileService, AccountProfileService>();
注入方法與只用接口注入不同。可以看到ConfigureServices(IServiceCollection services)
的參數是一個service集合,服務就是注入到這個動態集合里。AddScoped<T1,T2>()
方法中T2是服務類,T1是服務接口。所以每一個需要注入的服務都要有一個接口。
- 使用Add方法注入服務后怎么實例化服務?
有三種服務類型
1.Transient:每一次GetService都會創建一個新的實例。
什么時候是getservice呢?
public class AccountController : Controller
{
private readonly UserManager<Useraccount> _userManager;
private readonly SignInManager<Useraccount> _signInManager;
private readonly IAccountProfileService _profileService1;
private readonly IAccountProfileService _profileService2;
public AccountController(UserManager<Useraccount> userManager,SignInManager<Useraccount> siginManager
, IAccountProfileService profileService1,IAccountProfileService profileService2)
{
_userManager = userManager;
_signInManager = siginManager;
_profileService1 = profileService1;
_profileService2 = profileService2;
}
}
假設用戶發送一個請求,AccountController響應了。通過構造器生成兩個服務,如果是Transient那么兩個服務不同。如果是Scoped,在下一次http服務發送來之前兩個服務相同。Singleton都是同一服務。
2.Scoped:在同一個Scope內只初始化一個實例 。
3.Singleton:整個應用程序生命周期內只創建一個實例。
Core的優點在哪
可擴展性強:framework程序開始時選框架,之后添加框架麻煩。core采用服務注入的方式添加框架,靈活性更強。服務之間相互獨立,減少耦合。
中間件
https://www.cnblogs.com/liujiabing/p/11498163.html
-
什么是中間件:
出於安全性考慮,前端發送來的請求都不能直接輸入后端。需要管道對信息預處理,管道中的組件就是中間件。
主要功能:信息安全、對數據預處理、調度分配 -
中間件執行順序:
-
.netcore終端中間件:
-
Run
app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); });
執行該函數后會直接跳到管道末尾,后續中間件不會執行。
-
Map
app.Map("map1", app => { app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); });
第一個參數:匹配條件是HttpContext.Request.Path和預設值。
第二個參數:自定義管道。
可以根據這個函數設計多個管道分支。 -
MapWhen
map加約束版本app.MapWhen(context => context.Request.Query.ContainsKey("nihao"), app => { app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } );
-
路徑設置:
.netcore中MVC會默認設置有終端模式:
設置默認路由,就是設置終端路由。app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); });
老方法
app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
老方法需要吧mvc設置為無終端模式。
services.AddControllersWithViews( config => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); config.Filters.Add(new AuthorizeFilter(policy)); config.EnableEndpointRouting = false;//設置 } );