代码之家  ›  专栏  ›  技术社区  ›  Cade Roux

如何统一/简化此代码-事件处理/委派?

  •  0
  • Cade Roux  · 技术社区  · 16 年前

        private void ctxgrphAddBreakpoint_Click(object sender, EventArgs e)
        {
            Process p = GetProcess(viewer);
            if (p != null)
            {
                p.AddBreakpoint();
                BeginRefresh(false, false);
            }
        }
    
        private void ctxgrphRemoveBreakpoint_Click(object sender, EventArgs e)
        {
            Process p = GetProcess(viewer);
            if (p != null)
            {
                p.RemoveBreakpoint();
                BeginRefresh(false, false);
            }
        }
    
        private void ctxlistAddBreakpoint_Click(object sender, EventArgs e)
        {
            foreach (Process p in lvwProcessList.SelectedProcesses())
            {
                p.AddBreakpoint();
            }
            BeginRefresh(false, false);
        }
    
        private void ctxlistRemoveBreakpoint_Click(object sender, EventArgs e)
        {
            foreach (Process p in lvwProcessList.SelectedProcesses())
            {
                p.RemoveBreakpoint();
            }
            BeginRefresh(false, false);
        }
    

        private void ctxlistAction_Click(object sender, EventArgs e)
        {
            // I can unify the Viewer and ListView and implement some common interface,
            // so I'm pretty sure I can handle this part
            foreach (Process p in UIView.SelectedProcesses())
            {
                p.Action(); // What is the best way to handle this?
            }
            BeginRefresh(false, false);
        }
    

    我怎么去那里?

    4 回复  |  直到 16 年前
        1
  •  3
  •   Kelly S. French    16 年前

    访客模式?

        2
  •  2
  •   Nestor    16 年前

    ... += new System.EventHandler(ctxlistAction_Click); )在*。Designer.cs文件,并使它们指向相同的函数。

        3
  •  0
  •   mdm20    16 年前

    你不能把发送者直接转换到你的界面上吗?

     private void ctxlistAction_Click(object sender, EventArgs e)
     {
          UIView view = sender as UIView;
    
          if (view != null)
          {
    
             // I can unify the Viewer and ListView and implement some common interface,
             // so I'm pretty sure I can handle this part
             foreach (Process p in view.SelectedProcesses())
             {
                 p.Action(); // What is the best way to handle this?
             }
             BeginRefresh(false, false);
          }
      }
    
        4
  •  0
  •   dan    16 年前

    (请原谅我对“DoListAction”等名称的错误选择):

    readonly Action<Process> removeBreakpoint = p => p.RemoveBreakpoint();
    readonly Action<Process> addBreakpoint = p => p.AddBreakpoint(); 
    
    void DoSingleAction(Action<Process> action)
    {
         var p = GetProcess(viewer);
         if(p != null)
         {
             action(p); //invokes the action
             BeginRefresh(null,null);
         }
    }
    
    void DoListAction(Action<Process> action)
    {
        lvwProcessList.ForEach(action);
        BeginRefresh(false, false);
    }
    
    
    
    private void ctxgrphAddBreakpoint_Click(object sender, EventArgs e)
    {
        DoSingleAction(addBreakpoint);
    }
    
    private void ctxgrphRemoveBreakpoint_Click(object sender, EventArgs e)
    {
        DoSingleAction(removeBreakpoint);
    }
    
    private void ctxlistAddBreakpoint_Click(object sender, EventArgs e)
    {
        DoListAction(addBreakpoint);
    }
    
    private void ctxlistRemoveBreakpoint_Click(object sender, EventArgs e)
    {
        DoListAction(removeBreakpoint);
    }
    

    void DoAction(object sender, Action<Process>)
    {
         if(sender is ListView)
         {
             lvwProcessList.ForEach(action);
             BeginRefresh(false, false);
         }
         else if (sender is GraphView)
         {
             var p = GetProcess(viewer);
             if(p != null)
             {
                 action(p); //invokes the action
                 BeginRefresh(null,null);
             }
         }
         else {throw new Exception("sender is not ListView or GraphView");}
    }
    
    //and update all the handlers to use this, and delete DoSingleAction and DoListAction:
    private void ctxgrphAddBreakpoint_Click(object sender, EventArgs e)
    {
        DoAction(sender, addBreakpoint);
    }
    //etc.
    

    无论如何,在每个事件处理程序中,我认为你必须指定要采取的行动。我不确定在这种情况下继承或扩展方法是否真的是你的朋友,但使用扩展方法可能会是这样:

    //these two are in a separate static class
    public static InvokeAction(this ListView listView, Action<Process> action)
    { ... }
    public static InvokeAction(this GraphView listView, Action<Process> action)
    { ... }
    
    private void handler(object sender, Action<Process> action)
    { 
        var lv = sender as ListView;
        var gv = sender as GraphVeiw;    
        lv.InvokeAction(action); //(need to check for null first)
        gv.InvokeAction(action);
        if(lv == null && gv == null) {throw new Exception("sender is not ListView or GraphView");}
    }
    
    //then update all the handlers:
    private void ctxgrphAddBreakpoint_Click(object sender, EventArgs e)
    {
        handler(sender, addBreakpoint);
    }
    


    C#2/。NET 2.0

    在C#2中(VS2005),使用委托的第一种方式仍然有效,只是不能使用lambdas。(2.0有 Action<T>

    void removeBreakpoint(Process p) { p.RemoveBreakpoint(); }
    void addBreakpoint(Process p) { p.AddBreakpoint(); }
    
    //you could also do this, but it's overkill:
    readonly Action<Process> removeBreakpoint = delegate(Process p) { p.RemoveBreakpoint(); };
    readonly Action<Process> addBreakpoint = delegate(Process p) { p.AddBreakpoint(); };