工厂方法的构造函数上的类型约束

本文关键字:类型 约束 构造函数 方法 工厂 | 更新日期: 2023-09-27 18:25:16

我发现我的设计是错误的,并询问您如何解决我的问题。

所以我的案例:

我正在为类编写工厂方法,witch是从我的特殊基类派生而来的。所以我写了

public T MyFactory<T>() where T:MyBaseClass

但我的工厂方法的主要工作是获取一些特殊的参数,并将其传递给新对象的构造函数。MyBaseClass有这个构造函数:

public MyBaseClass(MySpecParam param){...}

但是不能保证从MyBaseClass派生的类型T具有这样的构造函数。

我看到的唯一解决方案是在MyBaseClass中添加new()约束和虚拟Init方法,这样工厂就可以安全地创建一个类型为T的新对象,然后用MySpecParam对象初始化它。

但是,MyBaseClass有这样的设计,所以如果不使用MySpecParam初始化,它是完全不可用的。用户可以用无参数构造函数创建MyBaseClass,得到完全无效的、未初始化的对象。我觉得这不好。

无法添加new(MySpecParam)约束。

我必须如何设计我的对象、构造函数和工厂方法?

工厂方法的构造函数上的类型约束

如果每个类只有一个公共构造函数,您可以通过反射找到它,确定它需要什么参数,并在调用构造函数时提供适当的值(仍然通过反射)。

否则,我假设您有一组有限的构造函数签名。在这种情况下,您将需要某种方法来确定要调用哪个构造函数;该决定可以部分地基于类型自变量CCD_ 13的身份。

编辑

如果出于评论中列出的原因,你不愿意使用反射,那么答案或多或少是"不,你不能那样做。"Michael Yoon建议使用IoC框架,该框架当然使用反射,也会出现运行时错误。根据我(Castle Windsor)的经验,性能从来都不是问题,由于配置错误导致的运行时错误几乎会在开发周期中立即出现。

另一种想法;这可能没有帮助,但可能值得考虑。您可以使用Func<T>来创建实例,甚至可以为不同类型的Func<T, TOut>Func<T1, T2, TOut>等重载工厂方法,在这些方法中您可以调用

var obj = FactoryMethod<SomeType>(() => new SomeType(23));

或者,考虑抽象的工厂模式。

听起来像是IoC容器的问题。如果您的工厂使用像StructureMap或Unity这样的容器,那么您的构造函数问题将不再是一个问题。工厂会要求StructureMap(例如)解析MyBaseClass,它会使用greedist构造函数返回一个MyBaseClass实例,递归地构建它的所有依赖项等等。

构造函数不是继承的,在接口上也不允许使用它们。这意味着每个类的构造函数仅特定于该类。这也意味着子类可以由基类组成,该基类没有与您的模式匹配的构造函数。如果你想有一种标准的方法来配置你的对象,我认为abstract Init(foo, bar, baz),在你的基类上,类似于你的想法,是最好的解决方案。如果对象在初始化之前被访问,您也可以实现内部逻辑来抛出,但不幸的是,您无法在编译时强制执行。