ASP.NET Core 2.2 基礎知識(一) 依賴注入
依賴:
類A用到了類B,我們就說類A依賴類B.如果一個類沒有任何地方使用到,那這個類基本上可以刪掉了.
public class Test { private MyDependency md = new MyDependency(); public void Print() { md.Print(); } }
public class MyDependency {public void Print() { Console.WriteLine("this is mydependency"); } }
上面的示例中,Test 類就依賴 MyDependency 類.
依賴倒置:
依賴倒置原則是五大原則之一:
1.上層模組不應該依賴於下層模組,它們共同依賴於一個抽象.
2.抽象不能依賴於具象,具象依賴於抽象.
什麼是上層?使用者就是上層,上例中,Test 類就是上層.
什麼是下層?被使用者就是下層.上例中,Test 類使用了 MyDependency 類, MyDependency 類就是下層.
上層不應該依賴下層,Test 類不應該依賴 MyDependency 類,因為如果 MyDependency 類變化了,就是把這種變化所造成的影響傳遞到上層 Test 類.
因此,上例按照依賴倒置原則修改如下:
public class Test { private IDepenency md = new MyDependency(); public void Print() { md.Print(); } }
publicinterface IDepenency { void Print(); } public class MyDependency : IDepenency { public void Print() { Console.WriteLine("this is mydependency"); } }
控制反轉(IoC):Inversion of Control
控制反轉是一種思想,所謂"控制反轉",就是反轉獲得依賴物件的過程.或許,叫"反轉控制"更容易理解.
上例雖然遵循了"依賴倒置原則",但是違背"開放封閉原則",因為如果有一天想修改 md 為 YourDependency 類的例項,則需要修改 Test 類.因此,我們需要反轉這種建立物件的過程.
internal class Program { private static void Main(string[] args) { Test test = new Test(new MyDependency()); test.Print(); Console.ReadKey(); } } public class Test { private IDepenency md; public Test(IDepenency depenency) { md = depenency; } public void Print() { md.Print(); } }
上例中,將 md 的建立過程"反轉"給了呼叫者.
依賴注入(DI):Dependency Inject
依賴注入設計模式是一種在類及其依賴物件之間實現控制反轉(IOC)思想的技術.
所謂依賴注入,就是由IoC容器在執行期間,動態地將某種依賴關係注入到物件之中。
我們先建立一個簡易的IoC容器(當然,實際的 IoC 容器複雜得多.):
public class IoCContainer { private Dictionary<Type, Object> dic; public IoCContainer() { Init(); } private void Init() { dic = new Dictionary<Type, object> { {typeof(IDepenency),new MyDependency() } }; } public T GetInstance<T>() { return (T)dic[typeof(T)]; } }
那麼,上例的呼叫,則可以修改成:
internal class Program { private static void Main(string[] args) { IoCContainer container = new IoCContainer();//建立一個容器 IDepenency dependency = container.GetInstance<IDepenency>();//獲取註冊的例項 Test test = new Test(dependency); test.Print(); Console.ReadKey(); } }
依賴注入分為3中:建構函式注入,屬性注入,方法注入,上例屬於建構函式注入.
ASP.NET Core 中的依賴注入
ASP.NET Core 內建的IoC容器,只支援建構函式注入,注入的方式如下:
在 Startup 類的 ConfigureServices 方法中註冊.
public void ConfigureServices(IServiceCollection services) {
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); //DI services.AddTransient<IDependency, MyDependency>(); }
使用:
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { private readonly IDepenency _dependency; public ValuesController(IDepenency dependency) { _dependency = dependency; } ...other codes
}
生存期
這是依賴注入設計原則裡一個非常重要的概念,ASP.NET Core 一共有3種生存期:
1.暫時(Transient) : services.AddTransient<IDependency, MyDependency>(); 顧名思義,這種生存期的物件是暫時的,每次請求都會建立一個新的例項.
2.作用域(Scoped) : services.AddScoped<IDepenency, MyDependency>(); 每次請求使用的是同一個例項.
3.單例(Singleton) : services.AddSingleton<IDepenency, MyDependency>(); 第一次請求時就建立,以後每次請求都是使用的相同的例項.
這種生存期的物件還有一種註冊方式: services.AddSingleton<IDepenency>(new MyDependency());
這種方式與其他所有方式的區別在於:如果 MyDependency 實現了 IDisposable ,那麼其他方式註冊的例項,容器會自動釋放,也就是說,容器建立的例項會自動釋放,但這種方式不會,因為這種方式註冊的例項不是容器建立的.
官方文件建議:
依賴注入是靜態/全域性物件訪問模式的替代方法.如果將其與靜態物件訪問混合使用,則可能無法實現依賴關係注入的優點。
ps 還沒搞明白的問題:
OperationService 依賴 IOperationTransient,IOperationScoped,IOperationSingleton,IOperationSingletonInstance,但是它只能註冊 暫時和作用域 生存期,不能註冊單例生存期
services.AddTransient<IOperationTransient, Operation>(); services.AddScoped<IOperationScoped, Operation>(); services.AddSingleton<IOperationSingleton, Operation>(); //通過程式碼將例項新增到容器中. services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty)); //OperationService 只能註冊臨時和作用域生存期 services.AddTransient<OperationService, OperationService>();