我觉得这是我应该已经知道的事情,但我今天并没有解雇所有引擎......
我有一个带有单个ctor的基类,它接受一个接口的实现,因为它是唯一的参数。我正在使用DI框架并且我的组件注册都已设置好并且工作正常。
当我从这个基类继承时,除非我将值传递给基础构造函数,否则我必须定义一个无参数的ctor,它会绕过DI。
现在我有:
public class MyObjectBase
{
IMyRequiredInterface _InterfaceImpl;
public MyObjectBase(IMyRequiredInterface interfaceImpl)
{
_InterfaceImpl = interfaceImpl;
}
...
}
public class AnotherObject : MyObjectBase
{
public AnotherObject()
{
}
...
}
所以,走出大门就失败了。当实例化AnotherObject时,我收到错误,表明没有基类ctor接受0参数。好的,我明白了。但现在我可以选择:修改后代类ctor以获取类似的参数并将该值传递给基本ctor,或者连接基类中的ctor链,这会迫使我绕过DI并创建一个具体的实现必需的接口并将其作为无参数ctor声明的一部分传递。
目标是满足基类的要求,而后代类不了解它。
也许我说这一切都错了,但这让我烦恼。有没有想过更好的方法来处理这个?我觉得我必须要错过一些简单的东西......
答案 0 :(得分:14)
正确的方法是:
public class AnotherObject : MyObjectBase {
public AnotherObject(IMyRequiredInterface interfaceImpl) :
base(interfaceImpl) {
}
}
您特别要求采用此方法以外的方法。为什么呢?
目标是满足基类的要求,而后代类不了解它。
这通常是错误的做法。你为什么要这样做?
根据您之后的评论,您应该使用(并配置您的容器使用)属性注入而不是构造函数注入。这将满足您的所有要求。
答案 1 :(得分:4)
错误......从MyObjectBase
继承的全部意义在于,就行为而言,你得到好的和坏的。如果在没有实现MyObjectBase
的对象的情况下无法创建IMyRequiredInterface
,则无法创建没有此类对象的子类。
那么当有人不给你那个时,你会怎么做?你有违约吗?
子类实例化实现IMyRequiredInterface
的东西是合理的,并通过super(...)
调用将其传递给超类构造函数。你能做到吗? (但是,正如我记得的那样,你可以在Java中对此有所了解,在做其他任何事情之前必须先调用super
。)
答案 2 :(得分:1)
这里有代码味道。如果从具有无参数构造函数的类继承,则意味着此基类的作者意图在不提供必要依赖性的情况下无法正常运行。如果从它继承并调用需要此依赖关系的基本方法,则如果未提供依赖关系,则代码可能会失败。因此,如果您确实认为应该完全覆盖此行为,则不必从此基类继承,否则只需复制继承类中的构造函数。
答案 3 :(得分:0)
如何在基类中提供不带参数的受保护构造函数?
class MyBase
{
readonly int _x;
public MyBase(int x)
{
_x = x;
}
protected MyBase()
{
_x = 0;
}
}
class MyChild : MyBase
{
public MyChild()
{
}
}
答案 4 :(得分:0)
我会这样做:
public class AnotherObject:MyObjectBase
{
public AnotherObject():MyObjectBase(new RequiredInterfaceImplementation())
{
}
}
其中:
public class RequiredInterfaceImplementation:IMyRequiredInterface
{
... your implementation
}
答案 5 :(得分:0)
大多数DI框架都具有使用属性将服务注入属性(Property Setter Injection)的功能,因此您可以尝试使用。
您可以继承子类,但子类必须知道如何创建或获取接口实现(使用ServiceLocator或其他东西)。
从DI的角度来看,它没有任何东西可以实现,因为该类只有一个空的构造函数(大多数使用具有最多参数的构造函数)并且没有任何属性告诉他做任何其他事情。
答案 6 :(得分:0)
我有同样的场景,我的基础(具体)类和子类具有依赖关系,我担心这些是不同的实例。
但是,Autofac(我相信其他容器工具)也有.InstancePerRequest(),它将根据Http请求共享相同的实例。
builder.RegisterType()为()InstancePerRequest();