我有一个接口和一个实现该接口的类。
我要求该类依赖于ITimer。创建一个私有成员并传入一个构造函数参数,并将私有成员分配给该构造函数参数。
如何使界面以某种方式声明此ITimer但不作为属性?它不像我不能正确测试MyClass,但我认为接口应该是一个类必须遵守的契约,因此我的类有一个依赖,所以如何使它出现在界面中?
public interface IMyInterface
{
void DoSomething();
}
public class MyClass : IMyInterface
{
private ITimer MyTimer;
public MyClass(ITimer timer)
{
MyTimer = timer;
}
public void DoSomething()
{
}
}
答案 0 :(得分:3)
这不起作用,并且很好,它不起作用:
您对ITimer
的依赖不是界面的一部分,它是界面的实施的一部分 - 因此将此隐藏在界面中是是对的。
如果界面的所有实现都需要依赖ITimer
(如果是这样的话,仅),那么你的接口声明应该附加在那里。
答案 1 :(得分:3)
使用C#中的接口无法做到这一点。你可以做的是继承一个接口的抽象类instread。
public abstract class AMyClass
{
protected ITimer MyTimer;
public AMyClass(ITimer timer)
{
MyTimer = timer;
}
public abstract void DoSomething();
}
public class MyClass : AMyClass
{
public override void DoSomething()
{
}
}
答案 2 :(得分:2)
如果您在接口上明确不想要ITimer
之类的依赖项,那么它听起来就像是一个实现细节,所以正确它不是定义为合同的一部分。一种方法是“忘记ITimer
;只有一些实现可能需要它,这是IoC / DI解析器的关注点。”
显然,构造函数不是界面的一部分。我能想到的另一件事(在保持IMyInterface
关闭API的同时)是拥有IMyInterfaceFactory
接口,Create
方法需要ITimer
- 但是然后强制执行特定的依赖项集,这可能无法反映实际的实现。
如果以上套件都没有,而ITimer
基本上是界面的一部分,我会将其正式作为界面的一部分。
答案 3 :(得分:2)
为什么财产不合适?你可以拥有一个带私人二手的房产,它可以完全满足您的需求。
其他选项是从带有受保护Timer的抽象基类派生,并同时实现接口。
理论上依赖注入是您正在寻找的。因此,可能需要了解Inversion of Control容器可能值得花时间。
答案 4 :(得分:1)
接口是类暴露的功能的合约。如果界面中没有ITimer
的自然位置,那么它在实现它的特定类中看起来像实现细节,因此应保留在类中。
答案 5 :(得分:0)
如果某个类可以在不使用ITimer
的情况下实现您的界面,那么它是否不符合该界面?这显然是。
使用ITimer
是一个实现细节,因此不应在界面中表示。