對象獲取三板斧
Unity 容器註冊映射後,提供三類核心解析方法(均含泛型與非泛型重載):
1. Resolve<T>()——單一默認實例
- 獲取默認映射(無名註冊)的實例
- 最常用,構建單一服務實例
container.RegisterType<IPlayer, Mp3Player>();
var player = container.Resolve<IPlayer>(); // 返回 Mp3Player 實例
圖 1:Resolve 默認映射解析
2. Resolve<T>(name)——命名映射精準獲取
- 獲取指定名稱註冊的映射實例
- 多實現切換、多租戶隔離核心 API
container.RegisterType<IPlayer, Mp3Player>("MP3");
container.RegisterType<IPlayer, CDPlayer>("CD");
var player = container.Resolve<IPlayer>("CD"); // 返回 CDPlayer
圖 2:Resolve 命名映射解析
3. ResolveAll<T>()——批量收集所有命名實例
- 返回所有有名映射的實例集合(
IEnumerable<T>)
- 無名映射不包含在內
- 插件系統、策略鏈、處理器管道典型場景
container.RegisterType<IPlayer, Mp3Player>("MP3");
container.RegisterType<IPlayer, CDPlayer>("CD");
container.RegisterType<IPlayer, DVDPlayer>(); // 無名
var players = container.ResolveAll<IPlayer>(); // 僅含 MP3、CD 兩個實例
圖 3:ResolveAll 僅收集命名映射
4. BuildUp<T>(existing)——為存量對象補全依賴
- 將外部創建的實例納入容器管理
- 執行屬性注入與方法調用注入
- 不執行構造函數注入(對象已構造)
- ASP.NET Page、Controller、WPF Window 等框架創建對象的標準接入點
// 模擬第三方庫創建對象
Telephone CreatePhone() => new Telephone(); // 無依賴注入
// 使用 BuildUp 補全
var tel = container.BuildUp<Telephone>(CreatePhone());
// tel.Dialer 現已注入(若標記 [Dependency])
圖 4:BuildUp 為現有實例注入屬性依賴
方法簽名完整列表
| 方法 | 泛型 | 非泛型 |
| Resolve | Resolve<T>() / Resolve<T>(name) | Resolve(Type) / Resolve(Type, name) |
| ResolveAll | ResolveAll<T>() | ResolveAll(Type) |
| BuildUp | BuildUp<T>(T) / BuildUp<T>(T, name) | BuildUp(Type, object) / BuildUp(Type, object, name) |
關鍵決策表:選哪個 API?
| 場景 | 推薦 API | 理由 |
| 常規服務解析 | Resolve<T>() | 默認映射,簡潔明確 |
| 多實現運行時切換 | Resolve<T>(name) | 命名映射精確控制 |
| 插件/處理器鏈收集 | ResolveAll<T>() | 自動聚合所有命名實例 |
| 框架創建對象需注入 | BuildUp<T>(existing) | 不控制構造,僅補全屬性/方法 |
| 動態類型解析 | Resolve(Type) | 插件加載、配置驅動類型 |
常見誤區提示
- ❌
ResolveAll 期望獲取無名映射 → 無名映射永不被 ResolveAll 收集
- ❌
BuildUp 期望執行構造函數注入 → 構造函數已執行完畢,不可重入
- ❌
Resolve 現有實例期望注入屬性 → Resolve 僅創建/獲取,不修改現有實例