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

时间:2008-10-10 20:51:50

标签: c# coding-style

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

3 个答案:

答案 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);
    }
}

最后一点:MethodInvokerAction都只是具有完全相同结构的代表。由于这种情况,两者都可以相互替换。这个命名冲突的根源来自遗产。最初(.Net 2.0)只有MethodInvokerAction(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。