我第一次使用构造函数注入,并且希望能够防御性地编写代码。
因此,如果我有一个带有构造函数和save方法的类,如下所示:
public SomeConstructor(string name, Object someObject)
{
_name= name;
_someObject= someObject;
}
public void Save()
{
// Does a database save
}
但是需要在这个Class中创建另一个不需要_someObject的相关方法,所以我创建了一个重载的链式构造函数:
public SomeConstructor(string name) : this(name, null)
{
}
如何使用带有1个参数的第二个构造函数并使用someObject为null的Save()成功阻止某人实例化该类?
我没有使用注射工具。
上面是一个简单的例子,在其中,你是正确的我只能像没有设置属性那样抛出null的异常。
我想避免的是在每种方法开始时进行的一系列验证检查。
答案 0 :(得分:4)
将您遇到的摩擦用作警告系统。这真的告诉你,你可能会走向低cohesion并违反Single Responsibility Principle。
如果是这种情况,请将该类重构为两个单独的类。
答案 1 :(得分:1)
您可以使用InvalidOperationException之类的运行时异常来防止这种情况。
如果某些人使用two-parameters-constructor实例化该类并尝试调用Save,只需检查“someObject”是否为null,如果是这样:
throw new InvalidOperationException("This method cannot be invoked in current object state");
另一方面,如果您的库使用第二个构造函数,并且不允许第三方库开发人员使用它,则此构造函数应该具有内部修饰符。
答案 2 :(得分:0)
public void Save()
{
if (_someObject == null)
throw new InvalidOperationException();
}
我猜这很明显。但是你真的无法创建一个不同构造类型的契约,除非你也将SomeConstructor
类型更改为decorator pattern。装饰器模式的作用是让你在运行时而不是编译时构建继承层次结构。
然后,您可以根据内部允许的操作创建不同的对象。对于可以使用Save
方法的前提条件轻松处理的内容,这是一些工作。但也许这就是你所需要的。如果你这样做,你可以在SomeConstructor
的构造函数中规定你的合同。
以下是一个例子:
interface ISomeConstructor
{
void Save();
}
class SomeConstructor
{
ISomeConstructor impl;
public SomeConstructor(string name, object someObject)
{
impl = new StringAndObject(name, someObject);
}
public SomeConstructor(string name)
{
impl = new JustString(name);
}
public void Save()
{
impl.Save();
}
}
StringAndObject
和JustString
类型实现了ISomeConstructor
,他们可以根据需要处理Save
方法。
这是装饰器模式的轻微变化,因为通常你会期望ISomeConstructor
作为参数传递给构造函数。
答案 3 :(得分:0)
IoC它只是一种动态解决依赖关系的方法,但不解决任何OO问题。 我会专注于一个好的OO设计,而不是试图找到一种方法来欺骗框架强制使用承包商而不是另一个。问题是如果你不使用IoC框架,你会怎么做? 可能检查SomeObject是否为null?