上一篇討論了 Autofac套件內部是如何運作的,稍微了解整個流程,雖然不是百分百都將所有細節都展現出來,但也可以了解近七、八成的主要執行方式。
這篇是要幫助,利用這個套件後,欲加上自己的註冊方式,或者遇到沒有支援的情境時要擴充一個註冊函示,要如何下手。
其實觀察套件供註冊的方式,與其它貢獻者貢獻出來的新的註冊函示,都是利用了C#的 Extension Method 的特性。這篇也僅僅是利用了此一特性,做了一個擴充的簡單範例。如果熟悉上一篇的內容,可以設計出獨特的註冊情境,利用它的 Container ComponentRegistry 、 RegistrationBuilder、 ComponentRegistration 等內容來操作。
而此篇只是利用改寫的方式,做一個開頭與釋例,將原本難以理解的 RegisterDecorator 做一個改寫,使之更簡便易讀操作。進而了解體驗如何做擴充。
首先來看套件提供的 RegisterDecorator 如何使用。裝飾者模式是我們很常運用的一套模式,是一種擴充物件的好方法。
想像一下要處理:
new DecoratorSuperSessionInjectionClass( new DecoratorSessionInjectionClass( new DecoratorInjectionClass(...) ) )
DecoratorInjectionClass 被 DecoratorSessionInjectionClass 裝飾,然後 DecoratorSessionInjectionClass 又被DecoratorSuperSessionInjectionClass裝飾。
一層又一層的裝飾,是不是有點複雜與易寫錯,如少一個括號等,某種程度上不太好讀與花費時間在偵錯。
如果可以DI注入的方式解決,是非常棒的。
於是Autofac提供了一個註冊方式(RegisterDecorator) 解決了此問題。
//Decorator Injection 註冊
builder.RegisterType().Named("Decorate");
builder.RegisterDecorator(
(c, inner) => new DecoratorSessionInjectionClass(inner), fromKey: "Decorate"
).Named("DecoratorSession");
builder.RegisterDecorator(
(c, inner) => new DecoratorSuperSessionInjectionClass(inner), fromKey: "DecoratorSession"
).Named("DecoratorSuperSession");
//Decorator Resolve 產生實例
var decoreteHandler = AutofacContainer.builder.ResolveNamed("DecoratorSuperSession");
如此可以實現使用類別 DecoratorSuperSessionInjectionClass 產生的實例,且確實包裝了對應的類別。
但是這種註冊方式有點難理解,每裝飾一層要寫一次.....令人有點頭痛。
於是,我們可以客製改寫一個較清楚的註冊,來達成一樣的作用,且程式碼某種程度較好理解。
將新增一個擴充函式 :
public static class ContainerBuilderExtensions
{
public static List< Autofac.Builder.IRegistrationBuilder<TService, LightweightAdapterActivatorData, Autofac.Builder.DynamicRegistrationStyle> >
RegisterDecoratorChain<TService>(
this ContainerBuilder builder,
List<DecoratorSeal<TService>> Decorators )
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
if (Decorators == null) throw new ArgumentNullException(nameof(Decorators));
List<Autofac.Builder.IRegistrationBuilder<TService, LightweightAdapterActivatorData, Autofac.Builder.DynamicRegistrationStyle>> lisBuilder =
new List<Autofac.Builder.IRegistrationBuilder<TService, LightweightAdapterActivatorData, Autofac.Builder.DynamicRegistrationStyle>>();
foreach (var decorator in Decorators)
{
lisBuilder.Add(
builder.RegisterDecorator<TService>(
decorator.DecoratorDelegateFunc, fromKey: decorator.fromWhichService
).Named<TService>(decorator.FinalDecoratorServiceName)
);
}
return lisBuilder;
}
}
傳入一個 List<DecoratorSeal<>>的裝飾目標集合,可以用泛型帶入要註冊的類別。而這個 DecoratorSeal 類別為裝飾目標的資訊,定義如下:
public class DecoratorSeal<TService>
{
public string fromWhichService; //要裝飾哪個服務
public Func<Autofac.IComponentContext, TService, TService> DecoratorDelegateFunc; // 委派裝飾執行的函示
public string DecoratorServiceName; //裝飾後的服務名稱
}
於是我們可以註冊此一擴充的裝飾者:
builder.RegisterType<DecoratorInjectionClass>().Named<IDecoratorClass>("Decorate"); //先定義好原始基本的類別對應的服務
List<DecoratorSeal<IDecoratorClass>> lisDecorators = new List<Autofac_EX.DecoratorSeal<IDecoratorClass>>();
lisDecorators.Add(
new DecoratorSeal<IDecoratorClass>()
{
DecoratorDelegateFunc = (c, inner) => new DecoratorSessionInjectionClass(inner),
fromWhichService = "Decorate",
DecoratorServiceName = "DecoratorSession"
}
); //DecoratorSessionInjectionClass 裝飾了 DecoratorInjectionClass
lisDecorators.Add(
new DecoratorSeal<IDecoratorClass>()
{
DecoratorDelegateFunc = (c, inner) => new DecoratorSuperSessionInjectionClass(inner),
fromWhichService = "DecoratorSession",
DecoratorServiceName = "DecoratorSuperSession"
}
); //DecoratorSuperSessionInjectionClass 裝飾了 DecoratorSessionInjectionClass
builder.RegisterDecoratorChain(lisDecorators);
執行好註冊後,於程式主體就可以resolve出實體:
var decoreteHandler = (DecoratorSuperSessionInjectionClass)AutofacContainer.builder.ResolveNamed<IDecoratorClass>("DecoratorSuperSession");
改成較易讀的方式,也只是改變傳入的方式,但利用VS的開發工具更快的原因是僅僅餵入參數該給的值,就達成註冊的效果。
這篇的目的為: 利用簡單的改寫現有的註冊函式來說明如何擴充autofac套件的註冊方式。
如果有任何新的情境產生新的註冊擴充,會再分享出來幫助各位。
When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.
評論