在 C# 中使用反射重写虚拟方法表

发布于 2024-11-04 18:06:27 字数 458 浏览 0 评论 0原文

有没有办法更改 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
    }
}

Is there a way to change the virtual methods tables in C#? like change where a virtual method is pointing?

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
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

拍不死你 2024-11-11 18:06:27

看看 LinFu

Linfu 作者的博客上有一个使用 LinFu 的示例。 AOP 可以拦截和更改对您不直接控制的类的方法的调用。

Take a look at LinFu.

On Linfu's author's Blog there's an example of using LinFu.AOP to intercept and change calls even to methods of classes that you don't control directly.

月下伊人醉 2024-11-11 18:06:27

您无法通过反射更改类型,只能反射现有类型。

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

You cannot change the types with reflection, you can only reflect over the existing types.

You can, however, build new types using Reflection.Emit and related classes, but short of recompiling your assembly, a.B(); in your example will always call A.B().

宁愿没拥抱 2024-11-11 18:06:27

丹尼,

你的实际问题是什么?给我描绘一幅“动态”“打破”现有的、经过测试的类定义的图片。请原谅我的怀疑……但我有丰富的脚本编写经验,因此我将采用在任何一天运行时都不会自行生成的代码。正是因为这个原因,我什至(有点)讨厌国际奥委会。

但是,如果您想“即时”创建一个覆盖(或实现)类定义,那么我想您会使用字节码生成(至少这就是您在 Java 中所做的)...这是一个论坛关于该主题的线程:http://bellyphant.com/2006/11/csharp_bytecode_ Generation

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

无论如何,祝你好运......这是一个有趣的问题。

干杯。基思.

Dani,

What's your ACTUAL problem? Paint me a picture of where-abouts "breaking" an existing, tested class definition "on the fly" would be desirable. Forgive my scepticism... but I have plenty of scripting experience, so I'll take code that doesn't generate itself as it's running any day. I even (sort of) hate IOC for just that reason.

However, If you want to create an overriding (or implementing) class-definitions "on the fly" then I suppose you'd use byte-code-generation (atleast that's what you'd do in Java)... Here's a forum thread on that topic: http://bellyphant.com/2006/11/csharp_bytecode_generation

You could also generate source-code, and compiling it on the fly. Here's a cute free little utils class to compile C# on the fly: http://www.agilekiwi.com/on_the_fly.htm

Good luck with it anyway... It's an interesting question.

Cheers. Keith.

从来不烧饼 2024-11-11 18:06:27

您可以将虚拟 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。您的代码将无法在高性能应用程序中使用。代表很快,反思很慢。

You can make virtual B call a default delegate you choose.
The following will allow inheritance and overriding: (actually overriding of already overriden :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();
    }
}
}

Output:

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

You can even call base.B(); in cB.B() which will effectively call the overriden delegate but will give this output:

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

I suggest you to take some similar approach or a design pattern approach and do not even think of reflection Emit. You code will be unusable in high performance applications. Delegates are fast, reflection is SLOW.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文