【问题标题】:Delegate Usage : Business Applications委托用法:业务应用程序
【发布时间】:2009-03-10 03:06:58
【问题描述】:

背景

鉴于“大多数”开发人员都是业务应用程序开发人员,我们最喜欢的编程语言的功能在我们正在使用它们的上下文中使用。

作为 C#/ASP.NET 应用程序开发人员,我倾向于只在处理 UI 事件时使用委托。事实上(这是我缺乏经验的一部分),我除了在事件中使用委托之外,我什至不知道一个好的上下文!这很可怕;但我发现还有其他开发人员在同一条船上。

注意:答案应与 .NET 2.0 相关。 .NET 3.0 将委托完全带到了一个不同的级别,这可能是一个单独的问题。

问题:

除了事件之外,委托有多大用处?它们在哪些业务应用程序上下文中最有用?

更新Jarrod Dixonhelpfully linked 到 MSDN 文档 regarding delegate usage,我必须承认我的 favorite Design Patterns Book 根本没有提出代表,所以我真的没有除了用于 UI 事件之外,还看到它们在使用中。为了扩展这个问题(只是一点点!),您可以为业务应用程序(或者实际上,任何必须处理相关问题的应用程序)提供哪些示例,以便更容易消化有关该主题的 MSDN 文档?

【问题讨论】:

    标签: c# .net asp.net delegates


    【解决方案1】:

    我认为这个问题反映了给猫剥皮的多种方法。我发现委托(和 lambda)几乎与“for”循环一样基本。

    这是我最近使用委托的一种情况(出于演示目的,格式和名称已更改:)

    protected T[] SortLines<T>(Func<T> createLine, IEnumerable<T> unsorted)
    where T : LineType
    {
        Func<IEnumerable<T>, IEnumerable<T>> sorter = (lines => lines);
    
        switch (settings.OrderSort)
        {
            case OrderSort.ByA: 
                sorter = (lines => lines.OrderBy(x => x.A)); break;
            case OrderSort.ByB:
                sorter = (lines => lines.OrderBy(x => x.B)); break;
    
            // and so on... a couple cases have several levels of ordering
        }
    
        bool requiresSplit = // a complicated condition
        if (requiresSplit)
        {
            var positives = unsorted.Where(x => x.Qty >= 0);
            var negatives = unsorted.Where(x => x.Qty <  0);
    
            return sorter(negatives).Concat(
                   new T[] { createLine.Invoke() }).Concat(
                   sorter(positives)).ToArray();
        }
        else
            return sorter(unsorted).ToArray();
    }
    

    因此,这会根据某些条件对一组项目进行排序,然后它要么返回已排序的整个列表,要么将其分成两部分,分别对两部分进行排序,并在它们之间放置一个分隔符。如果你不能表达“一种排序方式”的概念,那么祝你好运,这就是委托的用途。

    编辑:我猜 Concat 和 OrderBy 是特定于 3.0 的,但这仍然是基本思想。

    【讨论】:

    • lambdas 也是特定于 3.0 的。
    【解决方案2】:

    GUI 以外的...

    1. 事件调度;我的一些业务应用程序非常复杂,与硬件设备通信,并依靠事件队列来保持一切同步。这些应用使用委托进行事件分派。
    2. 业务规则;我的一些业务应用程序具有部分软编码能力,其中某些事件会触发保存在数据库中的某些规则。委托(在字典中)用于在客户端执行规则。 (可以支持插件,但不需要当前的)。
    3. 一般辅助线程(当然是使用 SafeThread 类!)

    【讨论】:

    • 第 2 点让我感兴趣;你有代码 sn-p 显示它是如何工作的吗?
    • @[Gortok]:规则命名动作并返回一个数据行,字典包含一个以名称为键的动作方法的委托; action 方法需要一个数据行
    【解决方案3】:

    据我所知,.NET 委托本质上是单方法接口的实现,没有所有的类声明。我希望我们在 Java 中拥有它们,就个人而言。想想一个比较器类:

    class MyComparator<Circle> extends Comparator<Circle> {
        public int compare(Circle a, Circle b) {
            return a.radius - b.radius;
        }
    }
    

    这种模式在任何有用的地方,委托都可能有用。

    我希望我是对的,但如果我错了,请继续投票;我已经很久没有看到任何 C# 了:)

    【讨论】:

    • 赞成大学尝试。这样一来,如果你被否决了,你就不能怪我。 :-D
    【解决方案4】:

    委托的另一个重要用途是作为状态机。如果您的程序逻辑包含重复的 if...then 语句来控制它所处的状态,或者如果您正在使用复杂的 switch 块,您可以轻松地使用它们来复制状态模式。

    enum State {
      Loading,
      Processing,
      Waiting,
      Invalid
    }
    
    delegate void StateFunc();
    
    public class StateMachine  {
      StateFunc[] funcs;   // These would be initialized through a constructor or mutator
      State curState;
    
      public void SwitchState(State state)  {
        curState = state;
      }
    
      public void RunState()  {
        funcs[curState]();
      }
    }
    

    我的 2.0 委托语法可能生锈了,但这是状态调度程序的一个非常简单的示例。还要记住,C# 中的委托可以执行多个函数,允许您拥有一个状态机,每个 RunState() 执行任意多个函数。

    【讨论】:

      【解决方案5】:

      任何时候当你执行任何异步操作时,比如进行webservice调用,你都可以使用delegate,所以当调用返回时,你可以发起delegate调用,让目标来处理事情。

      【讨论】:

        【解决方案6】:

        多年来我看到的一个常见模式(在各种语言中)是“冻结”将逻辑从循环中移到设置中的决定的结果。在伪代码中(因为技术因语言而异):

        some_condition = setup_logic
        ...
        while (not terminated) {
            data = obtain_data
            if (some_condition)
                process_one (data)
            else
                process_two (data)
        }
        

        关键是,如果some_condition 没有根据循环中的任何内容进行更改,那么重复测试它确实没有任何好处。代表/关闭/等。允许将上述内容替换为:

        some_condition = setup_logic
        if (some_condition)
            selected_process = process_one
        else
            selected_process = process_two
        ...
        while (not terminated) {
            data = obtain_data
            selected_process (data)
        }
        

        (当然,真正的函数式程序员会将设置编写为:

        selected_process = if (some_condition) process_one else process_two
        

        ;-)

        这很好地概括了多种选择(而不仅仅是两个)。关键思想是提前决定在未来的一个点(或多个点)采取什么行动,然后记住选择的行动而不是做出决定的价值基于。

        【讨论】:

          【解决方案7】:

          当您开始将代理视为功能构造时,代理会变得非常强大

          .Net 2.0 包括对匿名委托的支持,这构成了 Linq 扩展的一些功能概念的核心。匿名委托的语法比 Lambda 提供的要庞大一些,但很多核心功能模式都在 2.0 中。

          在 List 泛型类型中,您可以使用以下项目:

          1. ConvertAll() - 使用委托将列表的所有成员转换为另一种类型 (T)。这基本上是一个地图函数的实现
          2. Find() 和 FindAll 都接受委托,并将返回单个项目(在 Find() 的情况下)或导致传入的委托评估为 true 的所有项目。这提供了一个过滤器函数,以及一个谓词的定义(一个计算为布尔值的函数)
          3. 有一个 ForEach() 方法的实现,它接受一个委托。允许您对列表中的每个元素执行任意操作。

          Appart from List 特定项目,当您使用匿名委托上下文得到正确处理时,您可以实现类似闭包的结构。或者,在更实际的层面上做类似的事情:

          ILog logger = new Logger();
          MyItemICareAbout.Changed += delegate(myItem) { logger.Log(myItem.CurrentValue); };    
          

          而且它确实有效。

          还有 DynamicMethod 的东西,它允许您定义 IL 位(使用 Reflection.Emit),并将它们编译为委托。这为您提供了一个很好的替代纯反射的方法,例如映射层和数据访问代码。

          委托实际上是一种允许您将可执行代码表示为数据的结构。一旦你明白这意味着什么,就有很多事情可以做。与 3.5 相比,2.0 中对这些构造的支持是基本的,但仍然存在,并且仍然非常强大。

          【讨论】:

            【解决方案8】:

            委托通常用于事件调度,但这只是因为它们这样做很方便。委托对任何类型的方法调用都很有用。它们还具有许多附加功能,例如异步调用的能力。

            委托的基本原因是提供Closure,或调用函数及其状态的能力,通常是一个对象实例。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-05-30
              相关资源
              最近更新 更多