Замена кода котельной таблички - есть ли что-то плохое в этом коде?
Недавно я создал эти два (несвязанных) метода для замены большого количества кода котельной в моем приложении 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, хотя.