给定一个接口IFoo
interface IFoo {
void Do();
void Stuff();
}
假设有(遗留)类Foo1,Foo2,Foo3都实现了IFoo。
可以通过使用IFoo的某些方法来完成填充,或者对于较新的类,只需使用DoStuff()即可。实际上,人们可能会把它看作好像DoStuff()被遗忘了#34;在IFoo。
还有更新的类FooX(FooY,...)实现IFoo2,另外还有一个方法DoStuff();
interface IFoo2 : IFoo {
void DoStuff();
}
我需要接受IFoo对象,并且能够" Do Stuff"在上面。
//Let us assume foos = new IFoo[] {new Foo1(), new Foo2(), new Foo3(), new FooX()};
void MyMethod(IFoo[] foos){
foreach(foo in foos){
//DoStuff is not defined in IFoo
foo.DoStuff();
}
}
所以,我想在IFoo上为遗留类
定义一个扩展方法DoStuff()public static DoStuff(this IFoo self){
self.Do();
self.Stuff();
}
不幸的是,即使对于FooX,也始终会调用此扩展方法。
我可以做类似
的事情public static DoSomeStuff(this IFoo self){
if(self is IFoo2) {
(self as IFoo2).DoStuff()
} else {
self.Do();
self.Stuff();
}
}
void MyMethod(IFoo[] foos){
foreach(foo in foos){
foo.DoSomeStuff();
}
}
但是,MyMethod方法驻留在遗留项目中,目前还不知道IFoo2。是否可以在不使用IFoo2的情况下找到解决方案?
答案 0 :(得分:2)
你不应该扩展IFoo
接口。它是休息Interface Segregation principle。
如果这些对象在代码中表示完全相同的实体,则不应为它们使用不同的接口。
如果您想要实现接口IFoo
的类的扩展功能,但是不创建表示相同合同的第二个接口,则可以创建扩展方法。但是,如果您想更改IFoo
合同 - 重构遗留对象(添加缺少的实现)。
答案 1 :(得分:0)
只要您的变量的类型为IFoo
,就会调用扩展方法DoStuff
。解决这个问题的常用方法正是您在上一段中提出的建议,或者确保您在需要调用较新接口方法的地方使用IFoo2
而不是IFoo
。
答案 2 :(得分:0)
您可以创建一个抽象子类,该子类为当前未实现它的类实现Do和Stuff方法。
public abstract class abstractFoo : IFoo
{
public virtual void Do() {}
public virtual void Stuff(){}
}
如果可以继承这个抽象类
public class Foo: IFoo
{
// interface implementation required
}
becomes:
public class Foo: abstractFoo
{
// interface implementation NOT required
}
答案 3 :(得分:0)
恕我直言FooX
不应该开始实施IFoo
,并且应该重新考虑当前的建筑。
那说,并且不知道你正在对抗的确切限制,你能通过包装器发送IFooX
吗?如下所示:
public class FooXWrapper<T>: IFoo where T: FooX
{
readonly T foo;
bool doCalled;
public FooWrapper(T foo)
{
this.foo = foo;
}
public void Do()
{
doCalled = true;
}
public void Stuff()
{
if (!doCalled)
throw new InvalidOperationException("Must call Do");
foo.DoStuff();
}
}
这是一个丑陋的黑客,但考虑到情况......