[英]Type constraints on constructor for factory method
我发现我的设计是错误的,并询问您如何解决我的问题。
所以我的情况:
我正在编写工厂方法,对于类,女巫是从我的特殊基类派生的。 所以我写了
public T MyFactory<T>() where T:MyBaseClass
但是,我工厂方法的主要工作是获取一些特殊参数并将其传递给新对象的构造函数。 MyBaseClass
具有以下构造函数:
public MyBaseClass(MySpecParam param){...}
但是,不能保证从MyBaseClass
派生的T
类型具有此类构造函数。
我看到的唯一解决方案是向MyBaseClass
添加new()
约束和虚拟Init
方法,以便工厂可以安全地创建类型为T
的新对象,然后使用MySpecParam
对象对其进行MySpecParam
。
但是, MyBaseClass
具有这样的设计,因此,如果不使用MySpecParam
它,将完全无法使用。 用户可以使用MyBaseClass
参数构造函数创建MyBaseClass
并获得完全无效(未初始化)的对象。 我觉得不好
无法添加new(MySpecParam)
约束。
我该如何设计对象,构造函数和工厂方法?
如果每个类只有一个公共构造函数,则可以通过反射找到它,确定它需要使用哪些参数,并在调用构造函数时提供适当的值(仍然通过反射)。
否则,我假设您有一组有限的构造函数签名。 在这种情况下,您将需要某种方法来确定要调用的构造函数。 该决定可以部分地基于类型自变量T
的身份。
编辑
如果您出于评论中概述的原因不愿意使用反射,那么答案或多或少是“不,您不能那样做”。 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,然后将使用贪婪的构造函数返回MyBaseClass的实例,并递归地构建其所有依赖项,依此类推。
构造函数不能继承,也不能在接口上使用。 这意味着每个类的构造函数仅特定于该类。 这也意味着子类可以由不具有与您的模式匹配的构造函数的基类组成。 如果您想以一种标准的方式配置对象,我认为与您的想法类似,在您的基类上使用abstract Init(foo, bar, baz)
是最好的解决方案。 您也可以实现内部逻辑,如果在初始化对象之前访问了对象,则抛出该逻辑,但是不幸的是,您将无法在编译时强制执行该逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.