如何用Zenject为FooBarCollection注入并简化其内部FooBarItem的依赖注入?
解决Zenject中集合容器与子项依赖注入的单行配置问题
针对你遇到的问题,我们可以利用Zenject的**工厂绑定(BindFactory)**特性,结合集合类的封装,实现单行添加子项同时自动完成依赖注入,还能保证类型安全性。以下是具体实现方案:
方案一:封装集合类,内置工厂实现单行添加
1. 定义FooBarItem并声明工厂接口
首先在FooBarItem中声明工厂接口,Zenject会自动为该接口生成实现类,用于创建带依赖注入的实例:
public class FooBarItem { public string Name { get; } // 示例依赖项 private readonly SomeDependency _injectedDependency; // 构造函数注入依赖 public FooBarItem(string itemName, SomeDependency injectedDependency) { Name = itemName; _injectedDependency = injectedDependency; } // Zenject自动实现的工厂接口,用于创建FooBarItem实例 public interface Factory : IFactory<string, FooBarItem> { } }
2. 修改FooBarCollection,注入工厂并封装添加方法
在集合类中注入FooBarItem.Factory,并提供一个AddItem方法,内部调用工厂创建实例并完成注入:
public class FooBarCollection { private readonly FooBarItem.Factory _itemFactory; private readonly Dictionary<string, FooBarItem> _items = new(); // 注入FooBarItem的工厂 public FooBarCollection(FooBarItem.Factory itemFactory) { _itemFactory = itemFactory; } // 单行添加方法,自动完成依赖注入 public void AddItem(string itemName) { var newItem = _itemFactory.Create(itemName); _items.Add(itemName, newItem); } // 提供获取子项的方法 public FooBarItem GetItem(string itemName) => _items.TryGetValue(itemName, out var item) ? item : null; }
3. 在Installer中完成绑定
在你的Zenject Installer中绑定集合和工厂:
public class FooBarInstaller : MonoInstaller { public override void InstallBindings() { // 绑定FooBarCollection为单例 Container.Bind<FooBarCollection>().AsSingle(); // 绑定FooBarItem的工厂,关联到Zenject自动生成的实现 Container.BindFactory<string, FooBarItem, FooBarItem.Factory>().FromFactory(); } }
4. 使用方式
在任何需要的类中注入FooBarCollection后,只需一行代码即可添加带依赖注入的子项:
// 注入FooBarCollection private readonly FooBarCollection _fooBarCollection; public SomeClass(FooBarCollection fooBarCollection) { _fooBarCollection = fooBarCollection; } // 单行添加子项 _fooBarCollection.AddItem("ItemName1");
方案二:扩展方法实现(不修改原有集合类)
如果无法修改FooBarCollection的源码,可以通过扩展方法结合工厂实现单行添加:
1. 定义扩展方法
public static class FooBarCollectionExtensions { public static void AddInjectedItem(this FooBarCollection collection, FooBarItem.Factory itemFactory, string itemName) { var injectedItem = itemFactory.Create(itemName); // 假设FooBarCollection有公开的Add方法 collection.Add(injectedItem); } }
2. 使用方式
注入FooBarCollection和FooBarItem.Factory后,一行调用扩展方法:
private readonly FooBarCollection _fooBarCollection; private readonly FooBarItem.Factory _itemFactory; public SomeClass(FooBarCollection fooBarCollection, FooBarItem.Factory itemFactory) { _fooBarCollection = fooBarCollection; _itemFactory = itemFactory; } // 单行添加 _fooBarCollection.AddInjectedItem(_itemFactory, "ItemName2");
方案优势
- 单行添加:无需单独实例化子项再添加,一行代码完成创建+注入+加入集合
- 类型安全:工厂的
Create方法参数有明确类型约束,避免传参错误 - 符合Zenject规范:完全依赖Zenject的DI机制,无需直接调用
DiContainer实例化,保持代码一致性
内容的提问来源于stack exchange,提问作者JeffersonTD
相关产品推荐
相关产品推荐

