锅炉板代码更换 – 这个代码有什么不好的吗?

我最近创建了这两个(不相关的)方法来替换我的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 {}; 

这是件好事。 使它们成为扩展方法,以便更多地清理代码。 例如:

 //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);

由于事实,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) { var temp = evnt; if (temp != null) temp(sender, EventArgs.Empty); } } 

最后一点: MethodInvokerAction都只是具有完全相同结构的委托。 由于这种情况,两者都可以相互替换。 这个命名冲突的根源来自遗产。 最初(.Net 2.0)只有MethodInvokerAction(T) 。 但是由于事实,所有使用Action(T)人都会有一个Action并且发现使用MethodInvoker非常不自然。 所以在.Net 3.5中ActionAction(T1, T2, T3, T4)以及所有Func委托也加入了,但MethodInvoker在不做任何重大更改的情况下无法再删除。

额外:

如果你能够使用.Net 3.5,上面的代码就可以了,但如果你被固定到.Net 2.0,你可以像以前一样使用它作为普通函数,并用MethodInvoker替换Action

类似的模式对我没有任何问题。 我不知道你为什么要在MethodInvoker中包装Action。