Autofac中文文件--二、解析服務--1解析引數傳遞
阿新 • • 發佈:2019-02-11
Autofac 傳遞解析引數
註冊元件公開相應的服務之後,你可以從container構造器和子lifetime scopes 中解析服務。使用Resolve()方法來實現:var builder = new ContainerBuilder(); builder.RegisterType<MyComponent>().As<IService>(); var container = builder.Build(); using(var scope = container.BeginLifetimeScope()) { var service = scope.Resolve<IService>(); }你會發現在這個例子中,從一個lifetime scope 中解析服務,而不是直接在容器中解析,你也應該這樣做。 然而也有可能從根容器中解析元件,在你的應用中這樣做在一些情況下可能導致記憶體洩露。推薦你總是從一個lifetime scope中解析元件,以儘可能確保服務例項妥善處理和垃圾回收。在本節中你可以閱讀到很多關於控制範圍和生命週期的知識。 當解析服務時,Autofac 將自動連結服務的整個依賴層次結構,並且解析全面構建服務所需的任何依賴關係。如果你有迴圈依賴關係處理不當或缺失必須的依賴,你會得到一個DependencyResolutionException。 如果你有一個服務,不知道是否被註冊了,你可以嘗試使用ResolveOptional()或
// 如果 IService 被註冊, 它將被解析; // 如果沒有被註冊,將返回null; var service = scope.ResolveOptional<IService>(); // 如果 IProvider 被註冊, provider 變數將獲取此值, // 否則,你可以進行其他操作 // IProvider provider = null; if(scope.TryResolve<IProvider>(out provider)) { // Do something with the resolved provider value.ResolveOptional()和TryResolve()圍繞一個被註冊的特定服務的條件本質。如果服務被註冊,將嘗試解析,如果解析失敗,你將得到一個DependencyResolutionExceptionResolve()異常。如果你需要對一個服務進行條件判斷,此條件建立在此服務是否能被成功解析,用一個try/catch塊包裹Resolve()之後呼叫。}
1、傳遞解析引數
當解析服務時,你會發現需要為解析傳入引數。 Resolve()方法使用可變長度的引數列表,匹配註冊時相同的引數型別。另外,委託工廠和Func<T>隱式關係型別也允許在解析期間傳遞引數。1.1可用引數型別
Autofac 提供不同的引數匹配策略:- NamedParameter - 通過名稱匹配目標引數
- TypedParameter - 通過型別匹配目標引數
- ResolvedParameter - 靈活的引數匹配
1.2反射元件引數
有當你解析基於反射的元件時,該型別的建構函式可能需要你在執行時指定一個引數值,不適合在註冊時指定該值。你需要使用一個引數在Resolve()方法呼叫時提供這個值。 例如,你有一個配置讀取類 ,需要傳入一個配置節的名稱:public class ConfigReader : IConfigReader { public ConfigReader(string configSectionName) { // Store config section name } // ...read configuration based on the section name. }你可以像這樣,在解析時傳遞一個引數:
var reader = scope.Resolve<ConfigReader>(new NamedParameter("configSectionName", "sectionName"));作為註冊時引數,NamedParameter在案例中將對映到與命名相匹配的建構函式引數上。 如果你有多個引數,只需要把他們全部傳遞到Resolve()方法中:
var service = scope.Resolve<AnotherService>( new NamedParameter("id", "service-identifier"), new TypedParameter(typeof(Guid), Guid.NewGuid()), new ResolvedParameter( (pi, ctx) => pi.ParameterType == typeof(ILog) && pi.Name == "logger", (pi, ctx) => LogManager.GetLogger("service")));
1.3Lambda表示式元件引數
使用lambda表示式元件註冊,你需要在你的lambda表示式中新增引數處理,所以當呼叫Resolve()傳遞它們時,你可以利用它們。
在元件登錄檔達式中,你可以通過改變註冊時使用的委託簽名,來傳遞引數。而不是僅僅使用一個IComponentContext
引數,一個IComponentContext 和一個 IEnumerable<Parameter>:
// 註冊委託使用兩個引數: // c = The current IComponentContext to dynamically resolve dependencies // p = An IEnumerable<Parameter> with the incoming parameter set builder.Register((c, p) => new ConfigReader(p.Named<string>("configSectionName"))) .As<IConfigReader>();
現在,當你解析IConfigReader時,你的lambda表示式使用此引數來傳遞:
var reader = scope.Resolve<IConfigReader>(new NamedParameter("configSectionName", "sectionName"));