1. 程式人生 > >Autofac中文文件--二、解析服務--1解析引數傳遞

Autofac中文文件--二、解析服務--1解析引數傳遞

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()
TryResolve()解決:
// 如果 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 - 靈活的引數匹配
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"));

1.4傳遞引數不呼叫Resolve

全Autofac 支援兩種特性,允許你自動生成服務工廠,在解析時使用強型別引數列表。對於建立需要引數的元件例項,這是非常清潔的方式。