如何使用扩展方法使接口完整
How to use an extension method to make an interface complete
给定接口 IFoo
interface IFoo {
void Do();
void Stuff();
}
假设有(遗留)类 Foo1、Foo2、Foo3 都实现了 IFoo。
可以通过使用 IFoo 的一些方法来完成,或者在较新的 类 的情况下,只需使用 DoStuff()。实际上,人们可能会认为 DoStuff() 是 "forgotten" on 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是否可以找到解决方案?
只要您的变量具有 IFoo
类型,就会调用扩展方法 DoStuff
。解决这个问题的通常方法正是您在上一段中提出的,或者确保在您希望调用更新的接口方法的地方使用 IFoo2
而不是 IFoo
。
您可以创建一个抽象子class,为目前尚未实现的 classes 实现 Do 和 Stuff 方法。
public abstract class abstractFoo : IFoo
{
public virtual void Do() {}
public virtual void Stuff(){}
}
如果可以继承这个抽象class
public class Foo: IFoo
{
// interface implementation required
}
becomes:
public class Foo: abstractFoo
{
// interface implementation NOT required
}
你不应该像那样扩展 IFoo
接口。休息了 Interface Segregation principle.
如果这些对象在您的代码中表示完全相同的实体,则不应为它们使用不同的接口。
如果您想要扩展实现接口 IFoo
的 类 的功能,您可以创建扩展方法,但不要创建表示相同合同的第二个接口。但是,如果您想更改 IFoo
合同 - 重构遗留对象(添加缺少的实现)。
恕我直言 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();
}
}
这是一个丑陋的 hack,但考虑到情况...
给定接口 IFoo
interface IFoo {
void Do();
void Stuff();
}
假设有(遗留)类 Foo1、Foo2、Foo3 都实现了 IFoo。
可以通过使用 IFoo 的一些方法来完成,或者在较新的 类 的情况下,只需使用 DoStuff()。实际上,人们可能会认为 DoStuff() 是 "forgotten" on 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是否可以找到解决方案?
只要您的变量具有 IFoo
类型,就会调用扩展方法 DoStuff
。解决这个问题的通常方法正是您在上一段中提出的,或者确保在您希望调用更新的接口方法的地方使用 IFoo2
而不是 IFoo
。
您可以创建一个抽象子class,为目前尚未实现的 classes 实现 Do 和 Stuff 方法。
public abstract class abstractFoo : IFoo
{
public virtual void Do() {}
public virtual void Stuff(){}
}
如果可以继承这个抽象class
public class Foo: IFoo
{
// interface implementation required
}
becomes:
public class Foo: abstractFoo
{
// interface implementation NOT required
}
你不应该像那样扩展 IFoo
接口。休息了 Interface Segregation principle.
如果这些对象在您的代码中表示完全相同的实体,则不应为它们使用不同的接口。
如果您想要扩展实现接口 IFoo
的 类 的功能,您可以创建扩展方法,但不要创建表示相同合同的第二个接口。但是,如果您想更改 IFoo
合同 - 重构遗留对象(添加缺少的实现)。
恕我直言 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();
}
}
这是一个丑陋的 hack,但考虑到情况...