Как передать событие в метод? - PullRequest
24 голосов
/ 01 апреля 2010

Я хотел бы создать метод, который принимает событие в качестве аргумента и добавляет к нему eventHandler для правильной обработки. Как это:

У меня есть два события:

public event EventHandler Click;
public event EventHandler Click2;

Теперь я бы хотел передать определенное событие моему методу следующим образом (псевдокод):

public AttachToHandleEvent(EventHandler MyEvent)
{
    MyEvent += Item_Click;
}

private void Item_Click(object sender, EventArgs e)
{
    MessageBox.Show("lalala");
}

ToolStripMenuItem tool = new ToolStripMenuItem();
AttachToHandleEvent(tool.Click);

Возможно ли это?

Я заметил, что этот код работал нормально, вернулся в мой проект и заметил, что когда я передаю событие, объявленное в моем классе, оно работает, но когда я передаю событие из другого класса, оно все равно не работает. *

Что я получаю, это ошибка:

Событие 'System.Windows.Forms.ToolStripItem.Click' может появляться только на левой стороне из + = или - =

Ответы [ 6 ]

24 голосов
/ 01 апреля 2010

Мой оригинальный ответ был подходящим из класса, который определил событие, но с тех пор вы обновили свой вопрос, чтобы отразить, что вы хотите выполнить это за пределами определяющего класса, поэтому я поражен этим.

Только класс, определяющий событие, может ссылаться на неявную переменную-делегат, которую использует событие. Из-за пределов этого класса у вас есть доступ только к методам add и remove через += и -=. Это означает, что вы не можете делать то, что просите, напрямую. Однако вы можете использовать функциональный подход.

class A{
    public event EventHandler Event1;

    public void TriggerEvent1(){
        if(Event1 != null)
            Event1(this, EventArgs.Empty);
    }
}

class B{
    static void HandleEvent(object o, EventArgs e){
        Console.WriteLine("Woo-hoo!");
    }

    static void AttachToEvent(Action<EventHandler> attach){
        attach(HandleEvent);
    }

    static void Main(){
        A a = new A();
        AttachToEvent(handler=>a.Event1 += handler);
        a.TriggerEvent1();
    }
}
5 голосов
/ 01 апреля 2010

Я сделал это так:

public AttachToHandleEvent(Object obj, string EventName)
{
    EventInfo mfi = obj.GetType().GetEvent(EventName);
    MethodInfo mobj = mfi.GetAddMethod();
    mobj.Invoke(obj, new object[] { Item_Click});
}

private void Item_Click(object sender, EventArgs e)
{
    MessageBox.Show("lalala");
}

ToolStripMenuItem tool = new ToolStripMenuItem();
AttachToHandleEvent(tool "Click");

Спасибо всем за совет. Это решение не может быть сделано без вашей помощи.

2 голосов
/ 01 апреля 2010

Это невозможно. Вы можете использовать делегата вместо мероприятия, если это соответствует вашим потребностям.

2 голосов
/ 01 апреля 2010

Просто напишите tool.Click += Item_Click;

Edit: From MSDN "События могут быть вызваны только из класса или структуры, где они (оно) объявлены". Поэтому то, что вы пытаетесь сделать, невозможно. Не могли бы вы подробнее рассказать о своих потребностях? Почему вы хотите передать событие в качестве параметра?

1 голос
/ 01 апреля 2010
    delegate void doIt(object sender, object data);
    event doIt OnDoIt;

    void add(doIt theDel)
    {
        OnDoIt += theDel;
    }

    void doIt1(object a, object b)
    {
    }

    void doIt2(object a, object b)
    {
    }

    void add()
    {
        add(doIt1);
        add(doIt2);
    }
0 голосов
/ 30 октября 2015

Ваш вопрос говорит о том, что вы ошиблись некоторыми механизмами: Вы не можете пропустить события!

Скорее всего, вы хотите передать функцию в качестве параметра, поэтому вызывающий метод вызовет этот другой метод в какой-то момент. В техническом плане это делегат. Я предлагаю использовать уже определенный класс действий. Вот пример фрагмента:

void MyFunction (string otherArguments, Action onFinished){
    ...
    if (onFinished != null)
        onFinished.Invoke();
}

Приятно то, что при вызове MyFunction вы можете объявить действие, используя встроенный синтаксис:

MyFunction("my other argument", ()=>{
    ///do stuff here, which will be execuded when the action is invoked
});
...