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中,使其可用於模組掃描.