Замена кода котельной таблички - есть ли что-то плохое в этом коде?

Недавно я создал эти два (несвязанных) метода для замены большого количества кода котельной в моем приложении winforms. Насколько я могу судить, они работают нормально, но мне нужно какое-то подтверждение/совет о том, есть ли какие-то проблемы, которые я могу потерять.

(из памяти)

static class SafeInvoker
{
    //Utility to avoid boiler-plate InvokeRequired code
    //Usage: SafeInvoker.Invoke(myCtrl, () => myCtrl.Enabled = false);
    public static void Invoke(Control ctrl, Action cmd)
    {
        if (ctrl.InvokeRequired)
            ctrl.BeginInvoke(new MethodInvoker(cmd));
        else
            cmd();
    }

    //Replaces OnMyEventRaised boiler-plate code
    //Usage: SafeInvoker.RaiseEvent(this, MyEventRaised)
    public static void RaiseEvent(object sender, EventHandler evnt)
    {
        var handler = evnt;
        if (handler != null)
            handler(sender, EventArgs.Empty);
    }
}

ИЗМЕНИТЬ: см. соответствующий вопрос здесь

UPDATE

Следуя из проблем с тупиками (связанных с этим вопросом), я переключился с Invoke на BeginInvoke (см. объяснение здесь).

Другое обновление

Что касается второго фрагмента, я все чаще склоняюсь к использованию шаблона "пустой делегат", который исправляет эту проблему "в источнике", объявляя событие непосредственно с пустым обработчиком, например:

event EventHandler MyEventRaised = delegate {};

Ответ 1

Это хороший материал. Сделайте их методами расширения, хотя немного очистите свой код. Например:

//Replaces OnMyEventRaised boiler-plate code
//Usage: SafeInvoker.RaiseEvent(this, MyEventRaised)
public static void Raise(this EventHandler eventToRaise, object sender)
{
            EventHandler eventHandler = eventToRaise;

            if (eventHandler != null)
                eventHandler(sender, EventArgs.Empty);
}

Теперь о ваших событиях вы можете позвонить: myEvent.Raise(this);

Ответ 2

Из-за того, что Бенджол не знает, почему он помещает Action в MethodInvoker и broccliman, предназначенный для использования в качестве функции расширения, вот код очистки:

static class SafeInvoker
{
    //Utility to avoid boiler-plate InvokeRequired code
    //Usage: myCtrl.SafeInvoke(() => myCtrl.Enabled = false);
    public static void SafeInvoke(this Control ctrl, Action cmd)
    {
        if (ctrl.InvokeRequired)
            ctrl.BeginInvoke(cmd);
        else
            cmd();
    }

    //Replaces OnMyEventRaised boiler-plate code
    //Usage: this.RaiseEvent(myEventRaised);
    public static void RaiseEvent(this object sender, EventHandler evnt)
    {
        var temp = evnt;
        if (temp != null)
            temp(sender, EventArgs.Empty);
    }
}

Просто последнее примечание: MethodInvoker и Action - оба делегата, имеющие точно такую ​​же структуру. Из-за этого случая обе сменяются друг на друга. Корень этого столкновения имен происходит из наследия. В начале (.Net 2.0) было только MethodInvoker и Action(T). Но из-за того, что каждый, кто использовал Action(T), имел Action и счел очень неестественным взять MethodInvoker. Таким образом, в .Net 3.5 Action, Action(T1, T2, T3, T4) и все делегаты Func, которые добавлены тоже, но MethodInvoker больше не может быть удален без внесения каких-либо изменений.

Дополнительно:

Если вы можете использовать .Net 3.5, то приведенный выше код в порядке, но если вы привязаны к .Net 2.0, вы можете использовать его как обычную функцию, как прежде, и заменить Action на MethodInvoker.

Ответ 3

Подобные шаблоны сработали для меня без проблем. Я не уверен, почему вы обертываете Action в MethodInvoker, хотя.