转换为未明确实现的接口?

时间:2011-10-10 22:06:43

标签: c#

假设您定义了一些任意接口:

public interface IInterface {
    void SomeMethod();
}

让我们说有些类碰巧有匹配的公共接口,即使它们没有“实现IInterface”。 IE:

public class SomeClass {
    public void SomeMethod() {
       // some code
    }
}

是否有办法获得对IInterface实例的SomeClass引用? IE:

SomeClass myInstance = new SomeClass();
IInterface myInterfaceReference = (IInterface)myInstance;

6 个答案:

答案 0 :(得分:15)

没有办法做到这一点。如果类型没有实现接口,则无法转换为接口。实现与您想要的行为类似的行为的最佳方法是创建一个包装类型,为IInterface提供SomeClass的实现。

public static class Extensions {
  private sealed class SomeClassWrapper : IInterface {
    private readonly SomeClass _someClass;

    internal SomeClassWrapper(SomeClass someClass) {
      _someClass = someClass;
    }

    public void SomeMethod() {
      _someClass.SomeMethod();
    }
  }

  public static IInterface AsIInterface(this SomeClass someClass) {
    return new SomeClassWrapper(someClass);
  }
}

然后你可以进行以下调用

SomeClass myInstance = new SomeClass();
IInterface myInterface = myInstance.AsIInterface();

答案 1 :(得分:5)

如果您有权访问该源,您可以随时装饰该类,否则,您可以创建一个包装器:

public class InterfaceWrapper : IInterface
{
    private readonly SomeClass _someClass;

    public InterfaceWrapper(SomeClass someClass) { _someClass = someClass; }

    public void SomeMethod() { _someClass.SomeMethod(); }
}

答案 2 :(得分:4)

没有。仅仅因为两个类恰好具有相同名称的方法并不意味着它们遵守相同的合同。这就是您通过显式实现适当的接口来定义合同的原因。

答案 3 :(得分:4)

CSScriptLibrary.dll有一个扩展方法,可以将对象实例“对齐”到给定的接口:

public static T AlignToInterface<T>(this object obj) where T : class;

同时检查库的其余部分,它在反映C#脚本时是一个非常有用的API。

最好的问候。

答案 4 :(得分:3)

SomeClass实现的方法可能与接口中的方法具有相同的签名,但由于它不继承/实现接口,因此无法在此方案中使用强制转换 - 没有“意外的“一致性 - 你必须显式声明它实现特定接口的每个类。

答案 5 :(得分:2)

现在,这对dynamic很有用。这与获得强类型引用不同,因为这是不可能的,但如果它们恰好具有相同签名的成员,您仍然可以将其他不相关类型视为相同类型。

void DoSomethingThatCallsSomeMethodOnEitherType(dynamic pObject) =>
   pObject.SomeMethod();

SomeClass myInstance = new SomeClass();
IInterface myInterface = GetAnIInterfaceFromSomewhere();

DoSomethingThatCallsSomeMethodOnEitherType(myInstance);
DoSomethingThatCallsSomeMethodOnEitherType(myInterface);

这方面的一个具体示例是ListControlBeginUpdate / EndUpdate方法。这些方法是针对具体类型定义的,而不是基类型。使用dynamic,无论您使用的是ComboBoxListBox还是CheckedListBox,您仍然可以在不知道自己拥有哪一个的情况下致电BeginUpdate。 / p>