.Net Core中依赖注入服务使用总结
一、依賴注入
引入依賴注入的目的是為了解耦和。說(shuō)白了就是面向接口編程,通過(guò)調(diào)用接口的方法,而不直接實(shí)例化對(duì)象去調(diào)用。這樣做的好處就是如果添加了另一個(gè)種實(shí)現(xiàn)類,不需要修改之前代碼,只需要修改注入的地方將實(shí)現(xiàn)類替換。上面的說(shuō)的通過(guò)接口調(diào)用方法,實(shí)際上還是需要去實(shí)例化接口的實(shí)現(xiàn)類,只不過(guò)不需要我們手動(dòng)new 構(gòu)造實(shí)現(xiàn)類,而是交給如微軟的DI、Autofac這些工具去構(gòu)建實(shí)現(xiàn)類。我們只需要告訴它們,某個(gè)類是某個(gè)接口的實(shí)現(xiàn)類,當(dāng)用到的時(shí)候,工具會(huì)自動(dòng)通過(guò)構(gòu)造函數(shù)實(shí)例化類。
二、.Net Core中自帶的DI
本來(lái)想寫依賴注入源碼的講解的,看到網(wǎng)上有篇文章關(guān)于源碼講解的,很詳細(xì)、清楚,就不再寫了。地址:http://www.cnblogs.com/bill-shooting/p/5540665.html。我在這里就說(shuō)說(shuō)使用吧。
依賴注入有三種生命周期,每種生命周期的注入方式大同小異,下面我以作用域生命周期舉例,其他兩種跟這個(gè)不同,我會(huì)特別說(shuō)明。
下面為用到的兩個(gè)服務(wù)。
public class UserService : IUserService{
public string GetName()
{
return "UserName";
}
}
public interface IUserService
{
string GetName();
}
public class ConfigReader : IConfigReader
{
private string configFilePath;//需要傳一個(gè)路徑,去讀取路徑下文件的內(nèi)容
public ConfigReader(string configFileName)
{
this.configFilePath = configFileName;
}
public string Reader()
{
return File.ReadAllText(configFilePath);
}
}
public interface IConfigReader
{
string Reader();
}
1、最常用的注入方式,以接口形式暴露服務(wù)
services.AddScoped<IUserService, UserService>();
兩種注入方式是一個(gè)意思,這種方式適合實(shí)現(xiàn)類為無(wú)參構(gòu)造函數(shù)或者有參構(gòu)造函數(shù)中參數(shù)已經(jīng)被注入過(guò)了。
? 2、自己注入自己,以實(shí)現(xiàn)形式暴露服務(wù)
services.AddScoped<UserService>();
services.AddScoped(typeof(UserService));
這種注入方式適合只有實(shí)現(xiàn)類,沒(méi)有借口類的注冊(cè)。
3、需要傳參的構(gòu)造函數(shù)的類的注入
services.AddScoped<IConfigReader, ConfigReader>(x => { return new ConfigReader("c:/a.txt"); });services.AddScoped<IConfigReader>(x => { return new ConfigReader("c:/a.txt"); });
services.AddScoped(typeof(IConfigReader), x => { return new ConfigReader("c:/a.txt"); });
前兩個(gè)匿名方法參數(shù)是IServiceProvider,返回值為一個(gè)實(shí)例,第三個(gè)返回值是Object。上面舉的例子沒(méi)有用到IServiceProvider ,下面再舉一個(gè)例子。修改上面的UserService類,將構(gòu)造方法需要一個(gè)IConfigReader參數(shù)。
public class UserService : IUserService{private IConfigReader configReader;
public UserService(IConfigReader configReader)
{
this.configReader = configReader;
}
public string GetName()
{
return "UserName" + configReader.Reader();
}
}
注冊(cè)的時(shí)候,如下:
services.AddScoped<IConfigReader, ConfigReader>(x => { return new ConfigReader("c:/a.txt"); });//通過(guò)ServiceProvider獲取已經(jīng)注冊(cè)的IConfigReader
services.AddScoped<IUserService, UserService>(x => { return new UserService(x.GetService<IConfigReader>()); });
//或者
services.AddScoped<IUserService, UserService>(x => { return new UserService(new ConfigReader("c:/a.txt")); });
?單例類型的生命周期多了兩種注入方式:
services.AddSingleton<IConfigReader>(new ConfigReader("c:/a.txt"));
services.AddSingleton(typeof(IConfigReader), new ConfigReader("C:/a.txt"));
自帶的依賴注入工具也可以批量注入
var assembly = Assembly.GetExecutingAssembly().DefinedTypes
.Where(a => a.Name.EndsWith("Service") && !a.Name.StartsWith("I"));
foreach (var item in assembly)
{
services.AddTransient(item.GetInterfaces().FirstOrDefault(), item);
}
?注意:當(dāng)一個(gè)服務(wù)有多個(gè)實(shí)現(xiàn)時(shí),調(diào)用的時(shí)候通過(guò) IEnumerable<IPayService> PayServices 獲取所有的實(shí)現(xiàn)服務(wù)。
services.AddTransient<IPayService, AliPayService>();services.AddTransient<IPayService, WeChatPayService>();
使用的時(shí)候:
三、Autofac
1、以接口形式暴露服務(wù)
public IServiceProvider ConfigureServices(IServiceCollection services){
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();
var container = builder.Build();
return new AutofacServiceProvider(container);
}
2、通過(guò)實(shí)現(xiàn)類暴露服務(wù)
builder.RegisterType<UserService>();3、需要傳參的構(gòu)造函數(shù)的類的注入
builder.Register(c => new ConfigReader("c:/a.txt")).As<IConfigReader>();4、通過(guò)程序集注入
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).Where(c => c.Name.EndsWith("Service"))
.AsImplementedInterfaces();
總結(jié):
不論是微軟的依賴注入組件還是Autofac 原理都是先將接口和對(duì)應(yīng)的實(shí)現(xiàn)類注入到容器中,當(dāng)要使用的時(shí)候,組件會(huì)自動(dòng)通過(guò)構(gòu)造函數(shù)創(chuàng)建實(shí)例。這里有個(gè)問(wèn)題如果有個(gè)實(shí)現(xiàn)類有多個(gè)構(gòu)造函數(shù),組件會(huì)找滿足參數(shù)最多的那個(gè)構(gòu)造函數(shù)。
原文地址:https://www.cnblogs.com/MicroHeart/p/10861366.html
.NET社區(qū)新聞,深度好文,歡迎訪問(wèn)公眾號(hào)文章匯總?http://www.csharpkit.com?
總結(jié)
以上是生活随笔為你收集整理的.Net Core中依赖注入服务使用总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: .NET Core 3.0 可回收程序集
- 下一篇: SuperSocket 2.0 Prev