我最近创建了这两个(不相关的)方法来替换我的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);
}
}
编辑:参见相关问题here
更新
继死锁问题(与this question相关)后,我已从Invoke切换到BeginInvoke(请参阅解释here)。
另一次更新
关于第二个片段,我越来越倾向于使用'空委托'模式,它通过直接用空处理程序声明事件来解决这个'源'问题,如下所示:
event EventHandler MyEventRaised = delegate {};
答案 0 :(得分:15)
这是好事。使它们成为扩展方法,但要多清理一下代码。例如:
//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);
答案 1 :(得分:3)
由于事实,Benjol不知道,为什么他将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)
{
if (evnt != null)
evnt(sender, EventArgs.Empty);
}
}
最后一点:MethodInvoker
和Action
都只是具有完全相同结构的代表。由于这种情况,两者都可以相互替换。这个命名冲突的根源来自遗产。最初(.Net 2.0)只有MethodInvoker
和Action(T)
。但是由于这个事实,使用Action(T)
的所有人都会Action
发现MethodInvoker
并且发现Action
非常不自然。因此,在.Net 3.5 Action(T1, T2, T3, T4)
,Func
和所有Action
代理中也添加了,但MethodInvoker无法在不做任何重大更改的情况下删除。
如果你能够使用.Net 3.5,上面的代码很好,但如果你被固定到.Net 2.0,你可以像以前一样使用它作为正常功能,并用MethodInvoker
替换{{1}}
答案 2 :(得分:0)
类似的模式对我没有任何问题。我不知道你为什么要在MethodInvoker中包装Action。