代码之家  ›  专栏  ›  技术社区  ›  Benjol

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

  •  18
  • Benjol  · 技术社区  · 16 年前

    我最近创建了这两个(无关的)方法来替换WinForms应用程序中的许多Boiler Plate代码。据我所知,它们工作正常,但我需要一些安慰/建议,以确定是否有我可能遗漏的问题。

    (从记忆中)

    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 回复  |  直到 14 年前
        1
  •  14
  •   programmer    16 年前

    这是好东西。让它们成为扩展方法来清理代码。例如:

    //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(这个);

        2
  •  2
  •   Oliver    15 年前

    由于benjol不知道这个事实,他为什么把这个动作放到一个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 方法调用程序 Action(T) . 但事实上 动作(t) 她想拥有一个 行动 我觉得很不自然 方法调用程序 . 在.NET 3.5中, 行动 , Action(T1, T2, T3, T4) 以及所有 Func 也添加了代理,但如果不进行任何中断更改,则无法再删除MethodInvoker。

    附加:

    如果您能够使用.NET 3.5,那么上面的代码就可以了,但是如果您固定到.NET 2.0,那么您可以像以前一样使用它作为正常函数并替换它。 行动 通过 方法调用程序 .

        3
  •  0
  •   eulerfx    16 年前

    类似的模式对我来说没有问题。不过,我不知道你为什么要在MethodInvoker中包装动作。