好久沒寫 Autofac 筆記,記錄一則最近遇到的小需求。系統中針對介面(例如:IBlah)實作了多個型別,Resolve<IBlah>() 時希望透過參數指定傳回不同型別。
依據官方文件,實現這類需求的最簡單做法是使用 Named Service(具名服務)或 Keyed Service(鍵值對應服務), Register<T>() 後不使用 As<IBlah>(),而改用 Named<IBlah>("服務名稱") 或 Keyed<IBlah>(列舉值) 註冊。之後呼叫端改用 ResolveNamed<IBlah>("服務名稱") 或 ResolveKeyed<IBlah>(列舉值) 即可取得不同執行個體(Instance)。如此我們可為 IBlah 註冊多種型別,彼此以服務名稱字串或列舉值區隔,Resolve 時透過服務名稱字串或列舉值可取得指定型別的執行個體。Named 與 Keyed 功能相同,差異在於使用字串或列舉當參數,我傾向使用列舉以充分享受強型別的優勢。
講了一堆,其實用起來蠻簡單的,來段程式範例大家就明白了:
using Autofac;
using System;
namespace AutofacLab
{
publicinterface ISensor
{
string Detect();
}
publicclass TemperatureeSensor : ISensor
{
publicstring Detect()
{
return"It's hot";
}
}
publicclass SoundSensor: ISensor
{
publicstring Detect()
{
return"It's noisy";
}
}
publicenum SensorType
{
Temperature,
Sound
}
class Program
{
staticvoid _Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
//http://docs.autofac.org/en/latest/advanced/keyed-services.html
builder.RegisterType<SoundSensor>().Keyed<ISensor>(SensorType.Sound);
builder.Register((c) =>
{
returnnew TemperatureeSensor();
}).Keyed<ISensor>(SensorType.Temperature);
IContainer container = builder.Build();
var ss = container.ResolveKeyed<ISensor>(SensorType.Sound);
Console.WriteLine(ss.Detect());
var ts = container.ResolveKeyed<ISensor>(SensorType.Temperature);
Console.WriteLine(ts.Detect());
Console.Read();
}
}
}