Unity 是 Microsoft Patterns & Practices 推出的輕量級依賴注入容器。本文記錄初探 Unity 1.2 的學習歷程,從基本型別註冊開始,逐步探討多重註冊、具名解析與 ResolveAll 行為差異。
public interface ILogService { void Write(string message); }
public class CnsLogService : ILogService {
public void Write(string message) => Console.WriteLine($"Cns-exception msg:{message}");
}
// 使用 Unity
var container = new UnityContainer();
container.RegisterType<ILogService, CnsLogService>();
var service = container.Resolve<ILogService>();
service.Write("oh,exception occured!");
// 輸出:Cns-exception msg:oh,exception occured!
嘗試連續註冊兩個實作:
public class DataLogService : ILogService {
public void Write(string message) => DailyPractice.Utility.Log.AddLog(message);
}
namespace DailyPractice.Utility {
public class Log {
public static void AddLog(string message) => Console.WriteLine($"Data-exception msg:{message}");
}
}
// 連續註冊
container.RegisterType<ILogService, CnsLogService>()
.RegisterType<ILogService, DataLogService>();
var service = container.Resolve<ILogService>();
service.Write("oh,exception occured!");
// 輸出:Data-exception msg:oh,exception occured!
觀察:後註冊的 DataLogService 覆蓋先前註冊,CnsLogService 未被執行。
var services = container.ResolveAll<ILogService>();
foreach (var svc in services) {
svc.Write("haha, you have an exception 了吧!");
}
// 輸出:無任何輸出!
困惑:ResolveAll 回傳空集合?
參考 TerryLee 部落格,必須在註冊時指定名稱:
container.RegisterType<ILogService, CnsLogService>("CnsLogService")
.RegisterType<ILogService, DataLogService>("DataLogService");
var services = container.ResolveAll<ILogService>();
foreach (var svc in services) {
svc.Write("haha, you have an exception 了吧!");
}
// 輸出:兩個實作皆執行
Unity 容器中,
ResolveAll僅能解析具名註冊的型別對應。未指定名稱的註冊視為預設對應,僅能透過Resolve<T>()取得單一實例(最後註冊者勝出)。
RegisterType<TFrom, TTo>():預設對應,後者覆蓋前者RegisterType<TFrom, TTo>("name"):具名對應,可共存Resolve<T>():取得預設對應(單一實例)ResolveAll<T>():取得所有具名對應實例集合ResolveAll下一篇將探討 XML 組態檔配置與進階生命週期管理。