【发布时间】:2011-01-27 18:45:00
【问题描述】:
假设我们的系统可以执行动作,并且动作需要一些参数来完成它的工作。 我为所有动作定义了以下基类(为了您的阅读乐趣而进行了简化):
public abstract class BaseBusinessAction<TActionParameters>
: where TActionParameters : IActionParameters
{
protected BaseBusinessAction(TActionParameters actionParameters)
{
if (actionParameters == null)
throw new ArgumentNullException("actionParameters");
this.Parameters = actionParameters;
if (!ParametersAreValid())
throw new ArgumentException("Valid parameters must be supplied", "actionParameters");
}
protected TActionParameters Parameters { get; private set; }
protected abstract bool ParametersAreValid();
public void CommonMethod() { ... }
}
只有BaseBusinessAction 的具体实现知道如何验证传递给它的参数是否有效,因此
ParametersAreValid 是一个抽象函数。但是,我希望基类构造函数强制传递的参数始终有效,所以我添加了一个
对构造函数调用ParametersAreValid,当函数返回false 时抛出异常。到目前为止一切顺利,对吧?嗯,不。
代码分析告诉我“not call overridable methods in constructors”这实际上很有意义,因为当基类的构造函数被调用时
子类的构造函数尚未被调用,因此ParametersAreValid 方法可能无法访问某些关键成员变量
子类的构造函数会设置。
所以问题是:我该如何改进这个设计?
我是否将Func<bool, TActionParameters> 参数添加到基类构造函数?如果我这样做了:
public class MyAction<MyParameters>
{
public MyAction(MyParameters actionParameters, bool something) : base(actionParameters, ValidateIt)
{
this.something = something;
}
private bool something;
public static bool ValidateIt()
{
return something;
}
}
这会起作用,因为ValidateIt 是静态的,但我不知道...有没有更好的方法?
欢迎评论。
【问题讨论】:
-
+1,你让我写代码是为了实验。
-
ValidateIt 方法是否需要访问 MyParameters 私有数据才能对其进行验证?也许您应该将 MyParameters 实例传递给 ValidateIt。或者,MyParameters 可以验证自己吗?或者,您计划从 Action 基类实现的功能可以通过拥有对操作的引用而不是对它们进行超类型化来更好地实现?