1. 程式人生 > >Autofac官方文件(六)【註冊元件之程式集掃描】

Autofac官方文件(六)【註冊元件之程式集掃描】

Autofac可以使用約定來查詢和註冊程式集中的元件。 您可以掃描並註冊各種型別,也可以專門掃描Autofac模組。

掃描型別

否則稱為慣例驅動的註冊或掃描,Autofac可以根據使用者指定的規則從程式集中註冊一組型別:

var dataAccess = Assembly.GetExecutingAssembly();

builder.RegisterAssemblyTypes(dataAccess)
       .Where(t => t.Name.EndsWith("Repository"))
       .AsImplementedInterfaces();

每個RegisterAssemblyTypes()

呼叫將僅應用一組規則 - 如果要註冊多個不同組的元件,則需要多次呼叫RegisterAssemblyTypes()

過濾型別

RegisterAssemblyTypes()接受一個或多個程式集的引數陣列。 預設情況下,程式集中的所有公共具體類都將被註冊。 您可以使用一些提供的LINQ樣式謂詞來過濾要註冊的型別集。

要篩選已註冊的型別,請使用Where()謂詞:

builder.RegisterAssemblyTypes(asm)
       .Where(t => t.Name.EndsWith("Repository"));

要從掃描中排除型別,請使用Except()

謂詞:

builder.RegisterAssemblyTypes(asm)
       .Except<MyUnwantedType>();

Except()謂詞還允許您為特定的排除型別自定義註冊:

builder.RegisterAssemblyTypes(asm)
       .Except<MyCustomisedType>(ct =>
          ct.As<ISpecial>().SingleInstance());

可以使用多個過濾器,在這種情況下,它們將被應用邏輯AND。

指定服務

RegisterAssemblyTypes()

的註冊語法是單一型別的註冊語法的超集,所以像As()這樣的方法也可以使用程式集:

builder.RegisterAssemblyTypes(asm)
       .Where(t => t.Name.EndsWith("Repository"))
       .As<IRepository>();

As()Named()的可選過載接受lambda表示式,這些表示式決定了一個型別,它將提供哪些服務:

builder.RegisterAssemblyTypes(asm)
       .As(t => t.GetInterfaces()[0]);

與正常的元件註冊一樣,多個對As()的呼叫被加在一起。

增加了一些額外的註冊方法,以便更容易地建立通用約定:

Method Description Example
AsImplementedInterfaces() 將型別註冊為將其所有公共介面提供為服務(不包括IDisposable) builder.RegisterAssemblyTypes(asm).Where(t => t.Name.EndsWith(“Repository”)).AsImplementedInterfaces();
AsClosedTypesOf(open) 註冊可分配給已開啟泛型型別的已關閉例項的型別。. builder.RegisterAssemblyTypes(asm).AsClosedTypesOf(typeof(IRepository<>));
AsSelf() 預設值:註冊型別為自己的 - 當用另一個服務規範覆蓋預設值時也很有用. builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().AsSelf();

掃描模組

模組掃描是通過RegisterAssemblyModules()註冊方法來完成的,而註冊方法正是其名字所暗示的。 它掃描所提供的Autofac模組的程式集,建立模組的例項,然後將其註冊到當前的容器生成器。

例如,假設下面的兩個簡單模組類存在同一個程式集中,並且每個註冊一個元件:

public class AModule : Module
{
  protected override void Load(ContainerBuilder builder)
  {
    builder.Register(c => new AComponent()).As<AComponent>();
  }
}

public class BModule : Module
{
  protected override void Load(ContainerBuilder builder)
  {
    builder.Register(c => new BComponent()).As<BComponent>();
  }
}

不接受型別引數的RegisterAssemblyModules()的過載將註冊在提供的程式集列表中找到的實現IModule的所有類。 在下面的例子中,兩個模組都被註冊了:

var assembly = typeof(AComponent).Assembly;
var builder = new ContainerBuilder();

//註冊這兩個模組
builder.RegisterAssemblyModules(assembly);

RegisterAssemblyModules()與泛型型別引數的過載允許您指定(模組必須從中派生的)基本型別。 在下面的例子中,只有一個模組被註冊,因為掃描受到限制:

var assembly = typeof(AComponent).Assembly;
var builder = new ContainerBuilder();

//註冊模組但不包含BModule
builder.RegisterAssemblyModules<AModule>(assembly);

使用Type物件引數的RegisterAssemblyModules()的過載與通用型別引數過載類似,但允許您指定可能在執行時確定的型別。 在下面的例子中,只有一個模組被註冊,因為掃描受到限制:

var assembly = typeof(AComponent).Assembly;
var builder = new ContainerBuilder();

// 註冊模組但不包含BModule
builder.RegisterAssemblyModules(typeof(AModule), assembly);

IIS託管的Web應用程式

在IIS應用程式中使用程式集掃描時,根據程式集位置的不同,可能會遇到一些麻煩。 (這是我們的常見問題之一)

在IIS中託管應用程式時,應用程式首次啟動時,所有程式集都載入到AppDomain中,但當AppDomain被IIS回收時,程式集僅在需要時載入。

為避免此問題,請使用System.Web.Compilation.BuildManager上的GetReferencedAssemblies()方法來獲取引用程式集的列表:

var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();

這將強制引用的程式集立即載入到AppDomain中,使其可用於模組掃描.