简体   繁体   English

委托用法:业务应用程序

[英]Delegate Usage : Business Applications

Background背景

Given that 'most' developers are Business application developers, the features of our favorite programming languages are used in the context of what we're doing with them.鉴于“大多数”开发人员都是业务应用程序开发人员,我们最喜欢的编程语言的特性在我们正在使用它们的上下文中使用。

As a C# / ASP.NET Application developer, I tend to only use delegates when dealing with UI events.作为一名 C# / ASP.NET 应用程序开发人员,我倾向于在处理 UI 事件时只使用委托。 In fact (and this is part of my inexperience showing), I don't even know a good context other than events to use delegates in!事实上(这是我缺乏经验的一部分),除了使用代表的事件之外,我什至不知道一个好的上下文! This is quite scary;这很可怕; but I'm gathering that there are other developers in the same boat.但我正在收集其他开发人员在同一条船上。

NB : Answers should pertain to .NET 2.0.注意:答案应与 .NET 2.0 有关。 .NET 3.0 takes delegates to a different level entirely, and that'll likely be a separate question. .NET 3.0 将代表完全带到了一个不同的水平,这可能是一个单独的问题。

Question:问题:

Besides events, how useful are delegates, and in what Business Application contexts are they most useful?除了事件之外,委托有多有用,在哪些业务应用程序上下文中它们最有用?

Update : Jarrod Dixon helpfully linked to the MSDN documentation regarding delegate usage , and I must admit that my favorite Design Patterns Book didn't bring up delegates at all, so I haven't really seen them in use other than for UI events.更新Jarrod Dixon帮助链接到 MSDN 文档关于委托使用,我必须承认我最喜欢的设计模式书根本没有提出委托,所以除了 UI 事件之外,我还没有真正看到它们在使用中。 To expand this question (just a little bit,), What examples can you give for business applications (or really? any application having to deal with a relate-able problem) that would make it easier to digest the MSDN documentation on the subject?为了扩展这个问题(只是一点点),您可以为业务应用程序(或者真的?任何必须处理相关问题的应用程序)提供哪些示例,以便更容易消化有关该主题的 MSDN 文档?

I think this question reflects the many ways to skin a cat.我认为这个问题反映了给猫剥皮的多种方法。 I find delegates (and lambdas) nearly as fundamental as a "for" loop.我发现委托(和 lambda)几乎与“for”循环一样基本。

Here's one context in which I used delegates recently (formatting and names changed for presentation purposes:)这是我最近使用代表的一种情况(出于演示目的而更改了格式和名称:)

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

So this sorts a group of items based on some criteria, and then it either returns the whole list sorted, or it breaks it in two, sorts both halves separately, and puts a separator in between them.因此,这会根据某些标准对一组项目进行排序,然后它要么返回已排序的整个列表,要么将其分成两部分,分别对两半进行排序,并在它们之间放置一个分隔符。 Good luck doing this elegantly if you can't express the concept of "a way to sort something", which is what the delegate is for.如果你不能表达“一种排序方式”的概念,那么祝你好运,这就是委托的目的。

EDIT: I guess Concat and OrderBy are 3.0-specific, but this is still the basic idea.编辑:我猜 Concat 和 OrderBy 是特定于 3.0 的,但这仍然是基本思想。

Other than GUI...除了图形...

  1. event dispatching;事件调度; some of my business apps are quite complicated, talk to hardware devices, and rely on event queues to keep everything in synch.我的一些业务应用程序非常复杂,与硬件设备通信,并依靠事件队列来保持一切同步。 Delegates are used by these apps for event dispatching.这些应用程序使用委托来进行事件分派。
  2. business rules;商业规则; some of my business apps have a partial soft-coding ability, where certain events trigger certain rules that are kept in a database.我的一些业务应用程序具有部分软编码能力,其中某些事件会触发保存在数据库中的某些规则。 Delegates (in a Dictionary) are used to execute the rules on the client-side.委托(在字典中)用于在客户端执行规则。 (Plug-ins could be supported, but current are not needed). (可以支持插件,但不需要电流)。
  3. general secondary threads (using the SafeThread class, of course!)通用二级线程(当然是使用 SafeThread class!)

To my knowledge, a .NET delegate is essentially an implementation of a single-method interface, without all the class declaration hoopla.据我所知,.NET 委托本质上是单方法接口的实现,没有所有 class 声明。 I wish we had them in Java, personally.我希望我们亲自将它们放在 Java 中。 Think of a comparator class:想想比较器 class:

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

Anyplace this pattern is useful, a delegate could be useful instead.在这种模式有用的任何地方,委托都可能有用。

I hope I'm right, but go ahead and vote me down if I'm wrong;我希望我是对的,但 go 领先,如果我错了,请投票给我; it's been too long since I saw any C#:)我已经很久没有看到任何 C# 了:)

Another great use of delegates is as state machines.代表的另一个重要用途是 state 机器。 If your program logic contains repeated if...then statements to control what state it is in, or if you're using complicated switch blocks, you can easily use them to replicate the State pattern.如果您的程序逻辑包含重复的 if...then 语句来控制它所在的 state,或者如果您使用复杂的开关块,您可以轻松地使用它们来复制 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]();
  }
}

My 2.0 delegate syntax may be rusty, but that's a pretty simple example of a state dispatcher.我的 2.0 委托语法可能生锈了,但这是 state 调度程序的一个非常简单的示例。 Also remember that delegates in C# can execute more than one function, allowing you to have a state machine that executes arbitrarily many functions each RunState().还要记住,C# 中的代表可以执行多个 function,允许您拥有一台 state 机器,每个 RunState() 执行任意多个函数。

Anytime when you execute any asynchronous operations, such as making webservice calls, you can use delegate so when the call returns, you can initiate the delegate call for the target to handle things.每当您执行任何异步操作时,例如进行 web 服务调用,您都可以使用委托,因此当调用返回时,您可以发起委托调用,以便目标处理事情。

One common pattern I've seen over the years (in various languages) is to "freeze" the result of a decision to move logic out of a loop into a setup.多年来我看到的一种常见模式(在各种语言中)是“冻结”决定将逻辑从循环中移到设置中的结果。 In pseudo-code (because the technique varies with language):在伪代码中(因为技术因语言而异):

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

The point is that if some_condition doesn't change based on anything in the loop, then there's really no benefit from repeatedly testing it.关键是如果some_condition没有根据循环中的任何内容而改变,那么重复测试它真的没有任何好处。 Delegates/closures/etc.代表/关闭/等。 allow the above to be replaced by this:允许将上述内容替换为:

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

(Of course, a Real Functional Programmer would have written the setup as: (当然,真正的函数式程序员会将设置编写为:

selected_process = if (some_condition) process_one else process_two

;-) ;-)

This generalizes nicely to multiple alternatives (instead of just two).这很好地概括了多种选择(而不仅仅是两个)。 The key idea is to decide in advance what action to take at a future point (or points), and then remember the chosen action rather than the value on which the decision was based.关键思想是提前决定在未来一个(或多个)点采取什么行动,然后记住选择的行动,而不是决策所基于的价值

Delegates become extremely powerful when you start looking at them as functional constructs当您开始将委托视为功能构造时,委托会变得非常强大

.Net 2.0 included support for anonymous delegates, which formed the kernel of some of the functional concepts which were expanded upon by Linq. .Net 2.0 包括对匿名代表的支持,它形成了 Linq 扩展的一些功能概念的 kernel。 The syntax for an anonymous delegate is a bit bulkier than what Lambda's offer, but a lot of the core functional patterns are there in 2.0.匿名委托的语法比 Lambda 提供的要大一些,但很多核心功能模式都在 2.0 中。

In the List generic type you have the following items you can work with:在 List 泛型类型中,您可以使用以下项目:

  1. ConvertAll() - Uses a delegate to convert all the members of the list into another type (T). ConvertAll() - 使用委托将列表的所有成员转换为另一种类型 (T)。 This is basically an implementation of a Map Function这基本上是 Map Function 的实现
  2. Find() and FindAll, both take delegates, and will return you either a single item (in the case of Find()), or all items that cause the delegate passed in to evaluate to true. Find() 和 FindAll 都接受委托,并且将返回单个项目(在 Find() 的情况下)或导致传入的委托评估为真的所有项目。 This provides a Filter function, and also the definition of a Predicate (a function which evaluates to a boolean)这提供了一个过滤器 function,以及一个谓词的定义(一个 function 评估为布尔值)
  3. There is an implementation of a ForEach() method which takes a delegate.有一个 ForEach() 方法的实现,它接受一个委托。 Allowing you to perform an arbitrary operation against each element in the list.允许您对列表中的每个元素执行任意操作。

Appart from List specific items, when your using anonymous delegates context is handled correctly, so you can implement Closure like structures. Appart from List specific items,当您使用匿名委托上下文得到正确处理时,您可以实现类似闭包的结构。 Or, on a more practicle level do something like:或者,在更实际的层面上做类似的事情:

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

And it just works.它只是工作。

There is also the DynamicMethod stuff, which allows you to define bits of IL (using Reflection.Emit), and compile them as delegates.还有 DynamicMethod 的东西,它允许您定义 IL 位(使用 Reflection.Emit),并将它们编译为委托。 This gives you a nice alternative to pure reflection for things like Mapping layers, and data access code.这为您提供了一个很好的替代纯反射的方法,例如映射层和数据访问代码。

Delegates are really a construct that allows you to represent executable code as data.委托实际上是一个允许您将可执行代码表示为数据的结构。 Once you get your head around what that means, there are a whole lot of things that can be done.一旦你明白这意味着什么,就有很多事情可以做。 The support for these constructs in 2.0 was rudimentary when compared to 3.5, but still there, and still quite powerful.与 3.5 相比,2.0 中对这些构造的支持是基本的,但仍然存在,并且仍然非常强大。

Delegates are often used for event dispatch, however that's only because they are convenient to do so.委托通常用于事件调度,但这只是因为它们这样做很方便。 Delegates are useful for any kind of method invocation.委托对任何类型的方法调用都很有用。 They also have a number of additional features, such as the ability to invoke asynchronously.它们还具有许多附加功能,例如异步调用的能力。

The basic reason for a delegate though is to provide a Closure , or the ability to call a function along with it's state, which is usually an object instance.委托的基本原因是提供一个Closure或调用 function 及其 state 的能力,这通常是一个 object 实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM