基于输入参数返回不同类型对象的工厂实现疑问
解决方案
要解决这个泛型工厂的适配问题,核心是先统一所有Creator的类型标识,让DI能批量注入,再通过非泛型接口做类型中转。具体步骤如下:
1. 新增非泛型基接口
把ICreator<T>的公共能力抽成一个非泛型接口,这样所有泛型Creator都能被统一识别:
// 非泛型基接口,提供统一的类型判断和基础创建能力 interface ICreator { bool CanHandle(string type); BaseClass Create(); } // 泛型接口继承非泛型,保留强类型创建方法 interface ICreator<T> : ICreator where T : BaseClass { new T Create(); }
2. 修改Creator实现类
让每个Creator同时实现泛型和非泛型接口的方法,非泛型方法直接调用泛型版本:
class Creator1 : ICreator<MyClass1> { public bool CanHandle(string type) => type == "type1"; // 强类型创建方法 public MyClass1 Create() { return new MyClass1(); } // 实现非泛型接口的Create,内部转调泛型方法 BaseClass ICreator.Create() => Create(); } class Creator2 : ICreator<MyClass2> { public bool CanHandle(string type) => type == "type2"; public MyClass2 Create() { return new MyClass2(); } BaseClass ICreator.Create() => Create(); }
3. 实现总工厂类
通过DI注入所有ICreator实例,根据传入的type筛选出对应的Creator,调用创建方法:
class ObjectFactory { private readonly IEnumerable<ICreator> _allCreators; // 构造函数注入所有Creator实例 public ObjectFactory(IEnumerable<ICreator> creators) { _allCreators = creators; } // 基础方法:返回BaseClass类型实例 public BaseClass Create(string type) { var matchedCreator = _allCreators.FirstOrDefault(c => c.CanHandle(type)); if (matchedCreator == null) throw new ArgumentException($"不支持的类型标识:{type}"); return matchedCreator.Create(); } // 可选:强类型返回方法,适用于明确知道目标类型的场景 public T Create<T>(string type) where T : BaseClass { var matchedCreator = _allCreators.OfType<ICreator<T>>().FirstOrDefault(c => c.CanHandle(type)); if (matchedCreator == null) throw new ArgumentException($"类型{typeof(T)}不支持标识:{type}"); return matchedCreator.Create(); } }
为什么这么做?
原来的泛型ICreator<T>每个具体类型(比如ICreator<MyClass1>)都是不同的CLR类型,DI容器无法直接批量注入同一“类型族”的实例。通过非泛型基接口统一后,所有Creator都能被收集到IEnumerable<ICreator>中,既保留了强类型创建的优势,又解决了批量筛选和调用的问题。
内容的提问来源于stack exchange,提问作者demo
相关产品推荐
相关产品推荐

