我最近遇到了类似的问题。我有一个包含类层次结构的第三方类库(比如说 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;
}
我真正需要的是在 IBase 中定义并在每个后代类中重写的虚拟方法 AdditionalMethod(),但这是不可行的。因此,可能会想定义一个包含一组重载扩展方法的类:
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()。这不起作用:因为扩展方法是静态绑定的,所以总是调用第一个方法(即 AdditionalMethod(this IBase arg)),而不管 ext 的实际类型。通过在 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 类添加一个以 Derived2 作为参数的重载的 innerAddedMethod()。