Unity 容器啟動階段完成兩件事:建立契約→實現映射、綁定生命周期策略。本文以 IDialer/Dialer/ButtonDialer/PlateDialer/Telephone 模型演示。
| 管理器 | 引用策略 | 實例共享範圍 | 適用場景 |
|---|---|---|---|
| ContainerControlledLifetimeManager | 強引用 | 容器級單例 | 有狀態服務、昂貴資源、配置對象 |
| ExternallyControlledLifetimeManager | 弱引用 | 容器不阻止 GC,外部控制 | 緩存、作用域外部管理、需配合 GC |
| 無指定(默認) | 無引用 | 瞬態,每次新建 | 無狀態服務、輕量對象、請求級隔離 |
註冊時指定:RegisterType<TFrom,TTo>(new ContainerControlledLifetimeManager())。
container.RegisterType<IDialer, ButtonDialer>();
container.RegisterType<Dialer, ButtonDialer>(); // 基類映射同理
// 每次 Resolve 創建新實例
container.RegisterType<IDialer, ButtonDialer>(new ContainerControlledLifetimeManager());
// 首次 Resolve 創建,後續復用同一實例
container.RegisterType<IDialer, ButtonDialer>("Button");
container.RegisterType<IDialer, PlateDialer>("Plate");
// 解析時指定名稱:Resolve<IDialer>("Button")
container.RegisterType<IDialer, ButtonDialer>("Button", new ContainerControlledLifetimeManager());
var dialer = new ButtonDialer();
container.RegisterInstance<Dialer>(dialer); // 隱式 ContainerControlled
// 後續 Resolve 返回同一 dialer 實例
客戶端需載入配置並 Resolve(Type) 指定契約類型。
var parent = new UnityContainer();
parent.RegisterType<IDialer, ButtonDialer>(new ContainerControlledLifetimeManager());
var child = parent.CreateChildContainer();
child.RegisterType<IDialer, PlateDialer>(); // 子容器覆蓋,瞬態
// 子容器解析:優先查找自己,再向上委托父容器
var dialer1 = child.Resolve<IDialer>(); // PlateDialer (子容器)
var dialer2 = parent.Resolve<IDialer>(); // ButtonDialer (父容器)
客戶端:var child = container.CreateChildContainer(); section.Containers["ChildContainer"].Configure(child);
configSections 引用 UnityConfigurationSection<unity> 區塊聲明 typeAliases、containers、typeConvertersvar section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); section.Configure(container);| 方法組 | 核心簽名 | 關鍵參數 |
|---|---|---|
| RegisterType | RegisterType<TFrom,TTo>(name, lifetime) | name/生命周期/泛型非泛型 |
| RegisterInstance | RegisterInstance<T>(instance, name, lifetime) | instance/name/生命周期 |
| 子容器 | CreateChildContainer() / Dispose() | 父子隔離/繼承解析 |
掌握註冊 API 與生命周期組合,是驾馭 Unity 容器的基石。