標籤:style blog http color os io 使用 ar strong
在使用 Ioc 架構時,一般我們建議集中在一個稱為 Composition Root(其含義請參見下面的小注)的位置來註冊 (Register) 和解析 (Resolve) 服務。該做法的目的在於通過限制 Ioc 的使用場合,盡量減少應用程式本身對於 Ioc 架構的依賴。
這種模式固然能夠很好地解耦應用程式和 Ioc 架構,使我們能夠在需要的時候方便地更換 Ioc 架構,但它同時也帶來了一個問題:難道我們一定要在程式啟動時註冊所有服務嗎?有些服務並不一定會馬上用到,有一些服務甚至可能不會用到。在這種情況下,如果仍然按照上述模式,在程式啟動時將所有服務統統註冊到容器中,結果無疑會減緩程式的啟動速度,同時會加大記憶體消耗。
針對這個問題,我們在 My.Ioc 中給出了延遲註冊的解決辦法。它的原理其實很簡單:當應用程式向 My.Ioc 容器請求某個服務時,如果此時該服務尚未註冊,容器便會觸發一個 ObjectBuilderRequested 事件,並在事件參數中提供所請求的契約類型 (Contract Type) 和注入點資訊 (InjectionInfo),而訂閱了該事件的處理常式 (Event Handler) 便可以在這個時候根據契約類型和注入點資訊來決定是否向容器中註冊相應的服務以滿足應用程式需求。
用法很簡單,範例程式碼如下:
using System;using System.Diagnostics;using My.Ioc;namespace LazyRegistration{ public interface ILazyService { } public class LazyService : ILazyService { } class Program { static bool _eventHandled = false; static void Main(string[] args) { IObjectContainer container = new ObjectContainer(false); container.ObjectBuilderRequested += OnObjectBuilderRequested; var lazy = container.Resolve<ILazyService>(); Debug.Assert(lazy != null); Debug.Assert(lazy is LazyService); Console.WriteLine(_eventHandled); Console.ReadLine(); } static void OnObjectBuilderRequested(ObjectBuilderRequestedEventArgs args) { if (args.ContractType == typeof (ILazyService)) { args.Register<ILazyService, LazyService>(); _eventHandled = true; } } }}
小註:
Composition Root 的定義是“一個組合應用程式各個模組的位置,一個應用程式中應該僅有一個這樣的位置,這個位置通常是應用程式的進入點。例如,對於控制台應用程式來說,這個位置就是 Main 函數;對於 ASP.NET MVC 應用程式來說,這個位置可能是 global.asax;對於 WPF 應用程式來說,這個位置是 Application.OnStartup 方法...”。
源碼可從此處下載。
My.Ioc 程式碼範例——利用 ObjectBuilderRequested 事件實現延遲註冊