我最近遇到了类似的问题。我有一个包含类的层次结构的第三方类库(比方说IBase,Base和Derived,其中IBase实际上是一个接口)。
public interface IBase {...}
public class Base : IBase {...}
public class Derived : Base {...}
然后,我有一个类,它拥有一个IBase的参考分机。 ext的具体类型可以是Base和Derived。
public class MyClass {
// other stuff
public IBase ext;
}
其实我需要的是一个虚拟的方法AddedMethod()内广积定义,并在每个子类中重写,但是这并不可行。这样,一个可能会倾向于限定含有组重载扩展方法的类:
public static class MyExtensions
{
public static void AddedMethod(this IBase arg) {...}
public static void AddedMethod(this Base arg) {...}
public static void AddedMethod(this Derived arg) {...}
}
然后,上MyClass的对象调用ext.AddedMethod()。这是行不通的:因为扩展方法是静态绑定的,所以总是调用第一个方法(即AddedMethod(this IBase arg)),而不管实际类型的分机。 这个问题可以通过定义IBASE一个扩展方法可以绕过,然后使用反射来选择一个私有静态方法的正确的实例,其参数类型的实际类型传递给扩展方法匹配:
public static class MyExtensions
{
// just one extension method
public static void AddedMethod(this IBase arg){
// get actual argument type
Type itsType = arg.GetType();
// select the proper inner method
MethodInfo mi = typeof(MyExtensions).GetMethod("innerAddedMethod",
BindingFlags.NonPublic | BindingFlags.Static,
null,
new Type[] { itsType },
null);
// invoke the selected method
if (mi != null) {
mi.Invoke(null, new object[] { arg });
}
}
private static void innerAddedMethod(Base arg) {
// code for Base type arg
}
private static void innerAddedMethod(Derived arg) {
// code for Derived type arg
}
无论一个新的派生类Derived2应该被添加到IBase层次结构中,我们将不得不简单地向MyExtensions类添加一个重载的InnerAddedMethod(),它将Derived2作为它的参数。
是不是扩展名必须是静态的? – Alex 2013-03-15 14:40:10
是的,我错过了:/ – ozanbora 2013-03-15 14:40:59
如果它是一个B对象,但你有一个对它的引用,你是否需要*它来解析第二个扩展方法?毕竟,调用A引用上的虚拟方法无论如何都将在B对象上解析。你是否控制A和B班?如果是这样,你不应该使用扩展方法,但用普通方法修改类。 – nvoigt 2013-03-15 14:45:02