代表用法:业务应用程序

背景

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

作为C#/ ASP.NET应用程序开发人员,我倾向于在处理UI事件时仅使用委托。 事实上(这是我缺乏经验的一部分),我甚至不知道除了使用代表的事件之外的良好背景! 这非常可怕; 但是我知道在同一条船上还有其他开发商。

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

题:

除了事件,委托有多大用处,以及哪些业务应用程序上下文最有用?

更新 : Jarrod Dixon 有助于链接到关于委托使用的MSDN文档,我必须承认我最喜欢的设计模式书根本没有提出代表,所以除了UI事件之外我还没有真正看到它们的使用。 要扩展这个问题(只是一点点!),您可以为业务应用程序(或者实际上,任何必须处理相关问题的应用程序)提供哪些示例,以便更容易地消化关于该主题的MSDN文档?

我认为这个问题反映了皮肤猫的许多方法。 我发现委托(和lambdas)几乎和“for”循环一样重要。

这是我最近使用代理的一个上下文(格式和名称已更改用于演示目的:)

protected T[] SortLines(Func createLine, IEnumerable unsorted) where T : LineType { Func, IEnumerable> sorter = (lines => lines); switch (settings.OrderSort) { case OrderSort.ByA: sorter = (lines => lines.OrderBy(x => xA)); break; case OrderSort.ByB: sorter = (lines => lines.OrderBy(x => xB)); 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特定的,但这仍然是基本的想法。

GUI除外……

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

据我所知,.NET委托本质上是单方法接口的实现,没有所有的类声明hoopla。 我希望我们亲自在Java中使用它们。 想想比较器类:

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

任何地方这种模式都很有用,代表可能会有用。

我希望我是对的,但如果我错了,请继续投票。 自从我看到任何C#:)已经太久了

代表的另一个重要用途是作为状态机。 如果您的程序逻辑包含重复的if … then语句来控制它所处的状态,或者如果您使用复杂的开关块,则可以轻松地使用它们来复制State模式。

 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()执行任意多个函数。

无论何时执行任何异步操作(例如进行Web服务调用),都可以使用委托,这样当调用返回时,您可以启动委托调用以便目标处理事情。

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

 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) } 

(当然,Real Functional Programmer会将设置编写为:

 selected_process = if (some_condition) process_one else process_two 

😉

这很好地概括了多个替代方案(而不仅仅是两个)。 关键的想法是事先决定在未来一点(或多点)采取什么行动,然后记住所选行动而不是决策所依据的价值

当您开始将它们视为function构造时,代表会变得非常强大

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

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

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

来自List特定项目的公寓,当您正确处理使用匿名委托上下文时,您可以实现Closure之类的结构。 或者,在更实际的层面上执行以下操作:

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

它只是有效。

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

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

代表通常用于事件发送,但这只是因为它们很方便。 委托对任何类型的方法调用都很有用。 它们还具有许多其他function,例如异步调用的function。

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