使用反射来调用重写的基本方法

Kii*_*Kii 18 .net c# reflection

如何使用反射调用被派生类重写的基本方法?

class Base
{
    public virtual void Foo() { Console.WriteLine("Base"); }
}
class Derived : Base
{
    public override void Foo() { Console.WriteLine("Derived"); }
}
public static void Main()
{
    Derived d = new Derived();
    typeof(Base).GetMethod("Foo").Invoke(d, null);
    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

此代码始终显示"派生"...

Dog*_*ett 33

尽管当前的答案已被接受,但实际上可以通过使用这样的动态方法来更改原始类:

    static void Main(string[] args)
    {
        Derived foo = new Derived();
        foo.Foo();

        MethodInfo method = typeof(Base).GetMethod("Foo");
        DynamicMethod dm = new DynamicMethod("BaseFoo", null, new Type[] { typeof(Derived) }, typeof(Derived));
        ILGenerator gen = dm.GetILGenerator();
        gen.Emit(OpCodes.Ldarg_1);
        gen.Emit(OpCodes.Call, method);
        gen.Emit(OpCodes.Ret);

        var BaseFoo = (Action<Derived>)dm.CreateDelegate(typeof(Action<Derived>));
        BaseFoo(foo);

        Console.ReadKey();
    }
Run Code Online (Sandbox Code Playgroud)

你可以看到它仍然相对简单

  • 非常感谢.我从它创建了一个扩展,允许我这样做`typeof(Base).GetMethod("Foo").InvokeNotOverride(d,null);`.你可以在这里找到它:http://www.simplygoodcode.com/2012/08/invoke-base-method-using-reflection.html (4认同)

Kii*_*Kii 33

经过很长一段时间,我终于找到了比DynamicMethod更好的解决方案:

class CallOverride
{
    public static void Test()
    {
        var obj = new Override();
        var method = typeof(object).GetMethod("ToString");
        var ftn = method.MethodHandle.GetFunctionPointer();
        var func = (Func<string>)Activator.CreateInstance(typeof(Func<string>), obj, ftn);
        Console.WriteLine(func());
    }
}

class Override
{
    public override string ToString()
    {
        return "Nope";
    }
}
Run Code Online (Sandbox Code Playgroud)

此解决方案使用委托的标准构造函数签名:

public Delegate(object target, IntPtr ftn)
Run Code Online (Sandbox Code Playgroud)

其中target是目标实例,ftn是函数指针.它使用base方法的函数指针直接调用它,因此委托将指向实际的基本方法,而不是重写的方法.


Fré*_*idi 2

即使经过反思,你也无法做到这一点。C# 中的多态性实际上保证了始终会被调用,即使在强制转换回其基类Derived.Foo()的实例上也是如此。Derived

Base.Foo()从实例调用的唯一方法Derived是显式地使其可从Derived类访问:

class Derived : Base
{
    public override void Foo()
    {
        Console.WriteLine("Derived");
    }

    public void BaseFoo()
    {
        base.Foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 也许您需要考虑一下您的设计。没有理由做这些恶作剧。 (7认同)