使用Config註冊Module
在某些情境下或是需要註冊的類別太多時,會使用Autofac的Module來封裝註冊資訊,將相關的類別註冊寫在同一個Module裡
public class ServiceModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register<TestAService>(p =>
{
var testService = new TestAService();
testService._lifetimeScope = p.Resolve<ILifetimeScope>();
return testService;
}).Named<ITestService>("TestAService");
builder.RegisterType<TestBService>().Named<ITestService>("TestBService");
}
}
再透過RegisterModule的方式將Module註冊到Autofac的Container內
var builder = new ContainerBuilder();
builder.RegisterModule(new ServiceModule());
AutofacContainer = builder.Build()
如果當某些Module是系統必要註冊時,可以將註冊Module的事情移到Config裡,就不需要在寫在程式碼中。要將註冊Module寫到Config中,必須先安裝Autofac.Configuration,可以從Nuget中找到此套件
安裝完畢後,需要到App.config或者是Web.config加入以下設定
<configSections>
<section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration" />
</configSections>
再來,就可以將要固定註冊的Module寫到Config中
<autofac>
<modules>
<module type="AutofacConstructParameterLandmine_Lab.Model.ServiceModule, AutofacConstructParameterLandmine_Lab">
</module>
</modules>
</autofac>
並且,在程式碼中加入一行程式
builder.RegisterModule(new ConfigurationSettingsReader());
這樣就能會自動註冊寫在Config裡的Module。
附註: module type的格式,第一個為Module完成的名稱,第二個參數為Dll的名稱
使用Config設定Module內的屬性
有時候註冊某些元件時,會直接使用該元件封裝的Module。可是,在特定的情境下可能不需要註冊該元件裡所有的服務。舉個例子來說,當寫一個檔案搬移的元件時,可以同時將檔案複製多個位置,像是本機的硬碟加上網路空間。要達到這樣的功能只要針對不同的位置實作檔案複製的服務即可,再透過一個Manager負責對外讓人呼叫。但是,使用檔案複製元件的人可能沒有網路空間,單純的只是需要將檔案從原本的位置複製到另一個位置時,就不需要註冊檔案複製的所有服務。
這個時候,如果沒有開放參數用使用者設定所需要的服務時,使用者就必須自己註冊該元件要使用的服務,相當的不方便。所以,必須在Module中開放參數來設定要註冊的服務,並且可以將設定的數值寫在Config中。這樣的想法比較常見的做法有兩種
- 在Module中讀取Config的設定值
- 用Config的Module tag來設定Module中的屬性值
在這邊,筆者比較偏向使用第二個方法。因為,在Module中讀取Config的設定值,比較偏向是讀取服務內所需要的參數,概念上是內部需要的資訊去Config中讀取。而此情境是希望由外部來決定Module的流程,所以第二個方法比較適合。當需要設定Module內的屬性值時,只需要在Module tag中再加上Property tag
<autofac>
<modules>
<module type="AutofacConstructParameterLandmine_Lab.Model.ServiceModule, AutofacConstructParameterLandmine_Lab">
<properties>
<property name="IsRegisterTestAService" value="true" />
<property name="IsRegisterTestBService" value="false" />
</properties>
</module>
</modules>
</autofac>
Configa加上Property tag後,程式中的屬性就會有Config設定的值了
在Module裡就可以靠這些參數來設定哪些服務需要註冊
public class ServiceModule : Autofac.Module
{
public bool IsRegisterTestAService { get; set; }
public bool IsRegisterTestBService { get; set; }
protected override void Load(ContainerBuilder builder)
{
if(this.IsRegisterTestAService)
{
builder.Register<TestAService>(p =>
{
var testService = new TestAService();
testService._lifetimeScope = p.Resolve<ILifetimeScope>();
return testService;
}).Named<ITestService>("TestAService");
}
if(this.IsRegisterTestBService)
{
builder.RegisterType<TestBService>().Named<ITestService>("TestBService");
}
}
}
最後,在Autofac的Container內可以看到只有TestAService被註冊
結論
Moduel中所需要的參數,可以由不同的方法取得。但是,取得的方式還是必須要合理,上述的例子中,雖然都是讓Module中的變數取得外部設定的數值,但是在概念上是相差很遠的。使用合理概念寫出來的程式,這是很重要的一件事。
免責聲明:
"文章一定有好壞,文章內容有對有錯,使用前應詳閱公開說明書"