Специальные методы событий .NET (добавление / удаление / повышение / другое) - PullRequest
12 голосов
/ 24 декабря 2010

Мне было интересно узнать о методах EventInfo.GetRaiseMethod и EventInfo.GetOtherMethods.По-видимому, CLR поддерживает 4 вида методов, связанных с событиями: добавление, удаление, повышение и «другие».Но у событий, созданных в C #, есть только add и remove ... Я предполагал, что повышение использовалось в VB, так как вы должны указать метод RaiseEventкогда вы объявляете пользовательское событие, но, очевидно, это не так: GetRaiseMethod всегда возвращает ноль.

Итак, кто-нибудь знает:

  • какой смысл иметь поднять метод, связанный с событием, если он никогда не используется?Есть ли конкретная инструкция MSIL для вызова события с использованием этого метода?(Я не могу найти ничего подобного в кодах операций)
  • Какие "другие" методы возвращены (ну, на самом деле не возвращено) к GetOtherMethods?Что они должны делать?
  • Существуют ли типы в BCL, которые реализуют эти специальные методы?

Ответы [ 2 ]

7 голосов
/ 24 декабря 2010

Насколько я знаю, рейз мало используется, и я практически никогда не видел, чтобы он использовался. C ++ / CLI - практически единственный язык, который я знаю, который позволяет легко объявить метод повышение. Смотрите этот код, например:

using namespace System;

ref class Foo {

private:
    Action ^bar;

public:
    event Action ^Bar {
        void add (Action ^action)
        {
            Console::WriteLine ("add");
            bar += action;
        }

        void remove (Action ^action)
        {
            Console::WriteLine ("remove");
            bar -= action;
        }

        void raise ()
        {
            Console::WriteLine ("raise");

            if (!bar)
                return;

            Console::WriteLine ("raise for real");
            bar->Invoke ();
        }
    };
};

void hello ()
{
    Console::WriteLine ("hello");
}

void main ()
{
    Foo ^foo = gcnew Foo ();
    foo->Bar ();

    foo->Bar += gcnew Action (&hello);

    foo->Bar ();
}

Который при запуске естественно выдает:

C:\tmp>test
raise
add
raise
raise for real
hello

Чтобы ответить на ваш вопрос, нет никакого кода операции, чтобы вызвать событие, компилятор просто отправит вызов методу рейса:

  IL_0020:  ldloc.0
  IL_0021:  call       instance void Foo::raise_Bar()

Так же, как он генерирует вызов add_Bar.

Также ничего не стоит, так как C # позволяет вам вызывать событие исключительно в области действия типа, который объявляет событие-член, вы не можете получить код C # для вызова этого метода повышения. Так что нет, вы не найдете такого метода в BCL.

Что касается методов .other, я никогда не видел ни одного прикрепленного к событию. И я только видел, как они использовались один раз для свойств , и ни книга «Внутри IL ассемблера», ни «Аннотированный стандарт CLI» не дает никакой информации о них. Но в основном они позволяют вам прикреплять методы к свойству или событию, чтобы связать их семантически. Они не являются ни addon, ни removeon, ни raise методом, но они будут частью события, если язык должен это выразить. В то же время, единственный способ испустить его - использовать ilasm.

1 голос
/ 24 декабря 2010

Да, C # может использовать перегрузки добавления / удаления для регистрации обработчиков событий. EventInfo - это метаданные System.Reflection, которые используются при разборе подписи класса; метод RaiseEvent в Visual Basic не обязательно является тем же методом, что и этот, поскольку отражение создает для вас способ динамического вызова события или добавления обработчика события. RaiseEvent похоже на вызов события в C # как метод.

(Это частичный ответ, так как в вашем сообщении есть вопросы, я тоже не знаю ответа.)

...