【问题标题】:Boiler plate code replacement - is there anything bad about this code?锅炉板代码替换 - 这个代码有什么不好的吗?
【发布时间】:2008-10-10 20:51:50
【问题描述】:

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

另一个更新

关于第二个 sn-p,我越来越倾向于使用“空委托”模式,它通过直接使用空处理程序声明事件来“从源头”解决这个问题,如下所示:

event EventHandler MyEventRaised = delegate {};

【问题讨论】:

    标签: c# coding-style


    【解决方案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);

    【讨论】:

    • +1 用于扩展方法。我的想法与阅读代码时完全一样。
    • 您不需要额外的变量 eventHandler。 eventToRaise 参数已经是委托的安全副本。
    【解决方案2】:

    由于 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 非常不自然。因此,在 .Net 3.5 中,ActionAction(T1, T2, T3, T4) 和所有 Func 代表也添加了,但 MethodInvoker 无法在不进行任何重大更改的情况下被删除。

    补充:

    如果您能够使用 .Net 3.5,上面的代码很好,但如果您被固定到 .Net 2.0,您可以像以前一样将其用作正常功能,并将 Action 替换为 MethodInvoker

    【讨论】:

      【解决方案3】:

      类似的模式对我有用,没有任何问题。不过,我不确定您为什么要在 MethodInvoker 中包装 Action。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-25
        • 2012-02-01
        • 2013-08-18
        • 1970-01-01
        相关资源
        最近更新 更多