使用反射来覆盖C#中的虚方法表

| 有没有办法在C#中更改虚拟方法表?喜欢更改虚拟方法指向的位置?
class A
{
    public virtual void B()
    {
        Console.WriteLine(\"B\");
    }
}
class Program
{
    public static void MyB(A a)
    {
        Console.WriteLine(\"MyB\");
    }
    public static void Main(string[] Args)
    {
        A a = new A();
        // Do some reflection voodoo to change the virtual methods table here to make B point to MyB
        a.B(); // Will print MyB
    }
}
    
已邀请:
看看林富。 在Linfu \'s作者的Blog上,有一个使用LinFu.AOP来拦截和更改调用的示例,甚至可以更改对您不直接控制的类的方法的调用。     
您不能使用反射更改类型,只能反射现有类型。 但是,您可以使用Reflection.Emit和相关类来构建新类型,但是如果不重新编译程序集,示例中的
a.B();
将始终调用
A.B()
。     
丹妮 您的实际问题是什么?最好给我画一张关于“打破”现有的,经过测试的类定义“行进中”的图片。请原谅我的怀疑态度……但是我有丰富的脚本编写经验,因此我将采用在每天运行时不会自行生成的代码。出于这个原因,我什至讨厌IOC。 但是,如果您想“即时”创建一个覆盖(或实现)的类定义,那么我想您将使用字节码生成(至少这是您在Java中要做的) )...这是该主题的论坛主题:http://bellyphant.com/2006/11/csharp_bytecode_generation 您还可以生成源代码,并即时对其进行编译。这是一个可爱的免费小工具类,可以即时编译C#:http://www.agilekiwi.com/on_the_fly.htm 无论如何,祝你好运……这是一个有趣的问题。 干杯。基思     
您可以使虚拟B呼叫成为您选择的默认代理。 以下将允许继承和覆盖:(实际上是覆盖已覆盖的:D)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class A
{
    public delegate void delegateB();
    public delegateB _B;

    public A() {
      _B = B;
    }
    public void Override(delegateB newB)
    {
        _B = newB;
    }

    public virtual void B()
    {
        if (_B != null && _B != this.B) {
            Console.WriteLine(\"OVERRIDEN B IN A\");
            _B();
        }
        else {
        Console.WriteLine(\"VIRTUAL B IN A\");
        }
    }
}

    class cB : A {
        public override void B() {
            if (base._B != null && base._B != this.B)
            {
                Console.WriteLine(\"OVERRIDEN B IN B\");
                _B();
            }
            else
            {
                Console.WriteLine(\"IN B\");
            }

        }
    }

class Program
{
    class Overrider {
       public void MyB()
       {
           Console.WriteLine(\"MyB\");
       }
    }

    public static void Main(string[] Args)
    {
        A a = new A();
        a.B();
        Overrider ovr = new Overrider();
        a.Override(ovr.MyB);
        a.B(); // Will print MyB
        cB b = new cB();
        b.B();
        b.Override(ovr.MyB);
        b.B();
    }
}
}
输出:
VIRTUAL B IN A
OVERRIDEN B IN A
MyB
IN B
OVERRIDEN B IN B
MyB
您甚至可以在cB.B()中调用
base.B();
,这将有效地调用重写的委托,但会给出以下输出:
VIRTUAL B IN A
OVERRIDEN B IN A
MyB
IN B
OVERRIDEN B IN B
OVERRIDEN B IN A
MyB
我建议您采用一些类似的方法或设计模式方法,甚至不要考虑反射Emit。您的代码将无法在高性能应用程序中使用。代表们很快,反思很慢。     

要回复问题请先登录注册