有没有办法在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
}
}
答案 0 :(得分:4)
看看LinFu。
在Linfu's author's Blog上有一个使用LinFu.AOP拦截和更改调用的例子,甚至是你不直接控制的类的方法。
答案 1 :(得分:2)
您不能使用反射更改类型,只能反映现有类型。
但是,您可以使用Reflection.Emit和相关类构建新类型,但是如果不重新编译程序集,示例中的a.B();
将始终调用A.B()
。
答案 2 :(得分:1)
您可以将虚拟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();
,这将有效地调用overriden委托,但会给出这个输出:
VIRTUAL B IN A
OVERRIDEN B IN A
MyB
IN B
OVERRIDEN B IN B
OVERRIDEN B IN A
MyB
我建议你采取一些类似的方法或设计模式的方法,甚至不要想到反射Emit。您的代码在高性能应用程序中将无法使用。代表们很快,反思很慢。
答案 3 :(得分:1)
达尼,
你的实际问题是什么?给我画一张“在运行中”“破坏”现有的,经过测试的类定义的图片是可取的。请原谅我的怀疑......但我有很多脚本经验,所以我会把代码运行起来,因为它在任何一天都在运行。我甚至(有点)讨厌IOC。
但是,如果你想“动态”创建一个重写(或实现)类定义,那么我想你会使用字节码生成(至少你在Java中做的那样)......这是关于该主题的论坛帖子:http://bellyphant.com/2006/11/csharp_bytecode_generation
您还可以生成源代码,并在运行时对其进行编译。这是一个可爱的免费小工具类,可以动态编译C#:http://www.agilekiwi.com/on_the_fly.htm
无论如何,祝你好运......这是一个有趣的问题。干杯。基思。