Использование отражения для переопределения таблиц виртуальных методов в C # - PullRequest
4 голосов
/ 01 мая 2011

Есть ли способ изменить таблицы виртуальных методов в 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
    }
}

Ответы [ 4 ]

4 голосов
/ 01 мая 2011

Взгляните на LinFu .

В Блог автора Linfu есть пример использования LinFu.AOP для перехвата и изменения вызовов даже для методов классов, которые вы не контролируете напрямую.

2 голосов
/ 01 мая 2011

Вы не можете изменять типы с отражением, вы можете только отражать более чем существующие типы.

Однако вы можете создавать новые типы, используя Reflection.Emit и связанные классы, но без перекомпиляции вашей сборки, a.B(); в вашем примере всегда будет вызывать A.B().

1 голос
/ 01 мая 2011

Дани,

Какая у тебя ФАКТИЧЕСКАЯ проблема?Нарисуйте мне картину того, где-бы "сломать" существующее, проверенное определение класса "на лету" было бы желательно.Простите за мой скептицизм ... но у меня достаточно опыта написания сценариев, поэтому я возьму код, который не генерирует себя, так как работает в любой день.Я даже (своего рода) ненавижу МОК именно по этой причине.

Однако, если вы хотите создавать переопределенные (или реализующие) определения классов «на лету», тогда я полагаю, что вы будете использовать байт-код-поколение (по крайней мере, это то, что вы делаете в Java) ... Вот ветка форума на эту тему: http://bellyphant.com/2006/11/csharp_bytecode_generation

Вы также можете генерировать исходный код и компилировать его на лету.Вот классный бесплатный маленький класс утилит для компиляции C # на лету: http://www.agilekiwi.com/on_the_fly.htm

Удачи с ним в любом случае ... Это интересный вопрос.

Cheers.Кит.

1 голос
/ 01 мая 2011

Вы можете сделать виртуальный вызов 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

Вы даже можете вызвать base.B(); в cB.B ()который будет эффективно вызывать переопределенный делегат, но выдаст следующий вывод:

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

Я предлагаю вам воспользоваться некоторым подобным подходом или подходом шаблона проектирования и даже не думать об отражении Emit.Ваш код будет непригодным для высокопроизводительных приложений.Делегаты быстрые, отражение МЕДЛЕННОЕ.

...