使用reflection覆盖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 aB(); // Will print MyB } } 

看看林富 。

在Linfu 的作者博客上,有一个使用LinFu.AOP拦截和更改调用甚至是你不直接控制的类方法的例子。

您无法使用reflection更改类型,您只能反映现有类型。

但是,您可以使用Reflection.Emit和相关类来构建新类型,但是不能重新编译程序集aB(); 在您的示例中将始终调用AB()

达尼,

你的实际问题是什么? 给我画一张“在运行中”“破坏”现有的,经过测试的类定义的地方的图片是可取的。 请原谅我的怀疑……但我有很多脚本经验,所以我会采用不会自动生成的代码,因为它在任何一天都在运行。 出于这个原因,我甚至(有点)讨厌IOC。

但是,如果你想“动态”创建一个重写(或实现)类定义,那么我想你会使用字节代码生成(至少你在Java中做的那样)……这是一个论坛关于该主题的主题: http : //bellyphant.com/2006/11/csharp_bytecode_generation

您还可以生成源代码,并在运行时对其进行编译。 这是一个可爱的免费小工具类,可以动态编译C#: http : //www.agilekiwi.com/on_the_fly.htm

祝它好运…这是一个有趣的问题。

干杯。 基思。

您可以将虚拟B调用设置为您选择的默认委托。 以下将允许inheritance和覆盖:(实际覆盖已经覆盖: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(); aB(); Overrider ovr = new Overrider(); a.Override(ovr.MyB); aB(); // Will print MyB cB b = new cB(); bB(); b.Override(ovr.MyB); bB(); } } } 

输出:

 VIRTUAL B IN A OVERRIDEN B IN A MyB IN B OVERRIDEN B IN B MyB 

你甚至可以调用base.B(); 在cB.B()中,它将有效地调用overriden委托,但会给出这个输出:

 VIRTUAL B IN A OVERRIDEN B IN A MyB IN B OVERRIDEN B IN B OVERRIDEN B IN A MyB 

我建议你采取一些类似的方法或设计模式的方法,甚至不要想到reflectionEmit。 您的代码在高性能应用程序中将无法使用。 代表们很快,反思很慢。