一、IOC介紹
IOC:全名(Inversion of Control)-控制反轉
IOC意味着我們將對象的創建控制權交給了外部容器,我們不管它是如何創建的,我們只需要知道,當我們想要某個實例時,我們可以直接從這個外部容器中去拿,而再也不需要我們去new了,充分體現了DIP(依賴倒置原則),也體現了我們經常掛在嘴邊的面向接口編程。
DI:全名(Dependency Injection)-依賴注入
DI意味着將類型之間的依賴關系注入到DI容器中
在之前的.Net Framework中並沒有集成IOC,雖然Microsoft自己有一套"Unity",想要使用IOC+DI時,還需要我們自己去安裝包,進行三部曲等等各種操作
比較流行的IOC容器技術:Autofac、Unity、NInject。。。
二、.net core內置IOC容器(ServiceCollection)
1、打開NuGet包管理器,安裝 Microsoft.Extensions.DependencyInjection 包
2、實現代碼如下:
public interface ISqlHelper { void GetAll(); } public class SqlServerHelper : ISqlHelper { public void GetAll() { Console.WriteLine("this is "+typeof(SqlServerHelper)); } } static void Main(string[] args) { ServiceCollection services = new ServiceCollection(); services.AddTransient<ISqlHelper, SqlServerHelper>(); var provider=services.BuildServiceProvider(); var sqlHelper=provider.GetService<ISqlHelper>(); sqlHelper.GetAll(); Console.ReadKey(); }
運行結果如下:
當我們在執行業務邏輯時想要寫入一些日志(Log),必然會當然依賴這個類,那么會形成了SqlHelper類與Log類之前的依賴關系,我們可以將之前的依賴關系轉移到DI容器中,也就是依賴注入(DI),然后在DI容器獲取服務(對象)
示例代碼如下:
public interface ILog { void LogInfo(string msg); } public class Log : ILog { public void LogInfo(string msg) { Console.WriteLine(msg); } } static void Main(string[] args) { ServiceCollection services = new ServiceCollection(); services.AddTransient<ILog, Log>(); services.AddTransient<ISqlHelper, SqlServerHelper>(); var provider=services.BuildServiceProvider(); var sqlHelper= provider.GetService<ISqlHelper>(); sqlHelper.GetAll(); Console.ReadKey(); }
如果如下:
三、組件的生命周期
1、Single:單例,全局唯一實例
2、Scoped:作用域,在一個作用域中唯一實例,比如在Asp.Net Core應用程序中一次請求相當於一個Scoped
3、Transient:瞬時,每次的實例都是一個新的對象
Transient:
static void Main(string[] args) { ServiceCollection services = new ServiceCollection(); services.AddTransient<ISqlHelper, SqlServerHelper>(); var provider=services.BuildServiceProvider(); var sqlHelper=provider.GetService<ISqlHelper>(); sqlHelper= provider.GetService<ISqlHelper>(); Console.ReadKey(); }
結果如下:
Single:
static void Main(string[] args) { ServiceCollection services = new ServiceCollection(); services.AddSingleton<ISqlHelper, SqlServerHelper>(); var provider=services.BuildServiceProvider(); var sqlHelper=provider.GetService<ISqlHelper>(); sqlHelper= provider.GetService<ISqlHelper>(); Console.ReadKey(); }
結果如下:
Scoped:
1、一個作用域下:
static void Main(string[] args) { ServiceCollection services = new ServiceCollection(); services.AddScoped<ISqlHelper, SqlServerHelper>(); var provider=services.BuildServiceProvider(); var sqlHelper=provider.GetService<ISqlHelper>(); sqlHelper= provider.GetService<ISqlHelper>(); Console.ReadKey(); }
結果如下:
2、二個作用域下:
static void Main(string[] args) { ServiceCollection services = new ServiceCollection(); services.AddScoped<ISqlHelper, SqlServerHelper>(); var provider=services.BuildServiceProvider(); var scope1=provider.CreateScope();//在一個作用域下創建第一個子作用域 var scope2= provider.CreateScope();//在一個作用域下創建第二個子作用域 var sqlHelper= scope1.ServiceProvider.GetService<ISqlHelper>(); sqlHelper= scope2.ServiceProvider.GetService<ISqlHelper>(); Console.ReadKey(); }
如果如下:
注意:由於是控制台項目,只能用子作用域來體現作用域的特點,在web項目中,一次請求就相當於一個作用域