在前面幾篇 MEF 插件式開發 系列博客中,我分別在
DotNet Framework
和DotNet Core
兩種框架下實驗了 MEF 的簡單實驗,因爲DotNet Framework
由來已久,所以基於該框架下衍生出的不少優秀的 MEF 框架較多。可是對於DotNet Core
來講,狀況有所不一樣,因爲它自己對 DI 內置並提供支持,所以我嘗試使用它的全新 依賴注入(DI) 來作一些實驗。html
要想讓程序支持 DI,就須要爲項目安裝 Package:程序員
Install-Package Microsoft.Extensions.DependencyInjection -Version 2.1.1
而後,咱們就可使用強大的 DI 了。c#
在 DotNet Core,全部服務的註冊都是統一放到一塊兒的,而這個就是由 ServiceCollection 來接收的;其次,當服務註冊完畢後,還須要對服務進行初始化構建,構建後的結果做爲一個提供服務者返回,其對應的類型爲 ServiceProvider;最後,若是獲取某個已經註冊的服務的話,能夠經過 serviceProvider.GetService
下面,我分別從下面 4 個方面來體驗一下 DotNet Core
中強大的 DI
。框架
註冊服務須要涉及到服務的生命週期,所以,IServiceCollection 有 3 個不一樣的擴展方法:ide
示例代碼以下所示:函數
public interface IBaseSender { void Send(string message); } public interface ITransientSender : IBaseSender { } public class TransientSender : ITransientSender { public void Send(string message) => Console.WriteLine($"{GetHashCode()} {message}"); } public interface IScopedSender : IBaseSender { } public class ScopedSender : IScopedSender { public void Send(string message) => Console.WriteLine($"{GetHashCode()} {message}"); } public interface ISingletonSender : IBaseSender { } public class SingletonSender : ISingletonSender { public void Send(string message) => Console.WriteLine($"{GetHashCode()} {message}"); } class Program { private static readonly object locker = new object(); static void Main(string[] args) { var serviceProvider = new ServiceCollection() .AddTransient<ITransientSender, TransientSender>() .AddScoped<IScopedSender,ScopedSender>() .AddSingleton<ISingletonSender, SingletonSender>() .BuildServiceProvider(); using (var scope = serviceProvider.CreateScope()) { for (int i = 0; i < 2; i++) { serviceProvider.GetService<ITransientSender>().Send("ITransientSender"); scope.ServiceProvider.GetService<IScopedSender>().Send("IScopedSender"); serviceProvider.GetService<ISingletonSender>().Send("ISingletonSender"); } } Console.WriteLine("***********************************"); using (var scope = serviceProvider.CreateScope()) { for (int i = 0; i < 2; i++) { serviceProvider.GetService<ITransientSender>().Send("ITransientSender"); scope.ServiceProvider.GetService<IScopedSender>().Send("IScopedSender"); serviceProvider.GetService<ISingletonSender>().Send("ISingletonSender"); } } Console.ReadKey(); } }
程序輸出以下圖所示:ui
經過上圖咱們能夠了解到,插件
須要注意的是,在 ASP.NET Core 中,全部與 EF 相關的服務都應該經過 AddScoped<TInterface,T> 的方式注入。此外,若是想注入泛型的話,可藉助 typeof方式來注入。日誌
參數注入
public interface IBaseSender { void Send(); } public class EmialSender : IBaseSender { private readonly string _msg; public EmialSender(string msg) => _msg = msg; public void Send() => Console.WriteLine($"{_msg}"); } class Program { static void Main(string[] args) { var serviceProvider = new ServiceCollection() .AddSingleton<IBaseSender, EmialSender>(factory => { return new EmialSender("Hello World"); }) .BuildServiceProvider(); serviceProvider.GetService<IBaseSender>().Send(); Console.ReadKey(); } }
服務注入
public interface IBaseSender { void Send(); } public class EmialSender : IBaseSender { private readonly IWorker _worker; public EmialSender(IWorker worker) => _worker = worker; public void Send() =>_worker.Run("Hello World"); } public interface IWorker { void Run(string message); } public class Worker : IWorker { public void Run(string message) { Console.WriteLine(message); } } class Program { private static readonly object locker = new object(); static void Main(string[] args) { var serviceProvider = new ServiceCollection() .AddSingleton<IBaseSender, EmialSender>() .AddSingleton<IWorker, Worker>() .BuildServiceProvider(); serviceProvider.GetService<IBaseSender>().Send(); Console.ReadKey(); } }
在傳統的DotNet 框架下開發,注入是支持 參數、服務和屬性的,可是在 DotNet Core 平臺下目前只支持前兩種注入方式。
DotNet Core 中已經將 Logger
功能集成進來,只須要安裝相應的 Package 便可食用。
Microsoft.Extensions.Logging Microsoft.Extensions.Logging.Console Microsoft.Extensions.Logging.Debug
示例程序以下所示:
public interface IBaseSender { void Send(); } public class EmialSender : IBaseSender { private readonly IWorker _worker; private readonly ILogger<EmialSender> _logger; public EmialSender(IWorker worker, ILogger<EmialSender> logger) { _worker = worker; _logger = logger; } public void Send() { _worker.Run("Hello World"); _logger.LogInformation(MethodBase.GetCurrentMethod().Name); } } public interface IWorker { void Run(string message); } public class Worker : IWorker { public void Run(string message) { Console.WriteLine(message); } } class Program { private static readonly object locker = new object(); static void Main(string[] args) { var serviceProvider = new ServiceCollection() .AddSingleton<IBaseSender, EmialSender>() .AddSingleton<IWorker, Worker>() .AddSingleton(new LoggerFactory().AddConsole().AddDebug()) .AddLogging() .BuildServiceProvider(); serviceProvider.GetService<IBaseSender>().Send(); Console.ReadKey(); } }
此次作的幾個小實驗仍是頗有趣的,體驗了一下 DotNet Core 中強大的 DI 功能。和傳統的 DotNet Framework 相比,有不少改進的地方,這是值得每個 DotNet 程序員 去嘗試的一門新技術。