.NET Rx优于传统的事件? [英] Advantages of .NET Rx over classic events?

查看:152
本文介绍了.NET Rx优于传统的事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

.NET 4.0 beta 2 具有介绍了 IObservable IObserver 界面。

与传统.NET事件相比有什么优势?

What are the advantages compared to classic .NET events? Doesn't this solve the same problem?

推荐答案

可以使用IObservable作为事件,替换暴露事件属性的代码键入IObservable,但这不是真的点。

You can use IObservable as an event, replacing code that exposes events with properties of type IObservable, but that's not really the point.

有关IObservable有两件重要的事情:

There are two important things to understand about IObservable:


  1. 它统一了我们不知道在之前如何统一的两个概念:异步操作(通常返回一个值)和事件(通常永远是永远)。

  1. It unifies two concepts that we didn't know how to unify before: asynchronous operations (which typically return a single value) and events (which typically go on forever).

它是可组合的。与CLR事件,IAsyncResult或INotifyCollectionChanged不同,它允许我们从一般事件和异步操作中构建特定事件。

It is composable. Unlike CLR events, IAsyncResult, or INotifyCollectionChanged it allows us to build specific events out of general events and asynchronous operations.

这是一个在今天下午遇到的一个例子。

Here's an example I ran into at work just this afternoon.

在Silverlight中有一些效果可以应用于不能应用于正常控件的图像控件。为了克服这些限制,当控件的内容改变时,我可以等待它的视觉外观更新,并对其进行截图。然后我想隐藏其视觉表示,将其替换为快照,并将视觉效果应用于图像。现在我可以将图像效果应用到控件中(假设它不是交互式的)。

In Silverlight there are some effects you can apply to an image control that cannot be applied to a normal control. To get around these limitations when a control's content is changed I can wait for its visual appearance to be updated and take a screenshot of it. Then I want to hide its visual representation, replace it with the snapshot, and apply the visual effects to the image. Now I can apply image effects to a control (assuming it's not interactive).

这个程序是微不足道的,但是它必须是异步的。我必须等待两个连续的异步操作才能完成,然后才能对图像应用效果:

This program would be trivial but for the fact that it must be asynchronous. I must wait for two consecutive asynchronous operations to complete before I can apply effects to the image:


  1. 控件的内容已更改

  2. 控件的视觉外观已更新

以下是使用Rx解决此问题的方法:

Here's how I'd solve this problem using Rx:

// A content control is a control that displays content.  That content can be
// anything at all like a string or another control.  Every content control contains
// another control: a ContentPresenter.  The ContentPresenter's job is to generate
// a visual representation of the Content property. For example, if the Content property
// of the ContentControl is a string, the ContentPresenter creates a TextBlock and inserts
// the string into it.  On the other hand if the Content property is another control the 
// ContentPresenter just inserts it into the visual tree directly.
public class MyContentControl : ContentControl
{
   // A subject implements both IObservable and IObserver.  When IObserver methods
   // are called, it forwards those calls to all of its listeners.
   // As a result it has roughly the same semantics as an event that we can "raise."
   private Subject<object> contentChanged = new Subject<object>();

   // This is a reference to the ContentPresenter in the ContentControl's template
   private ContentPresenter contentPresenter; 

   // This is a reference to the Image control within ContentControl's template.  It is displayed on top of the ContentPresenter and has a cool blur effect applied to it.
   private Image contentImageControl; 

   public MyContentControl()
   {
      // Using Rx we can create specific events from general events.
      // In this case I want to create a specific event ("contentImageChanged") which
      // gives me exactly the data I need to respond and update the UI.
      var contentImageChanged = 
         // get the content from the content changed event
         from content in contentChanged
         where content != null
         // Wait for the ContentPresenter's visual representation to update.
         // ContentPresenter is data bound to the Content property, so it will
         // update momentarily.
         from _ in contentPresenter.GetLayoutUpdated().Take(1)
         select new WritableBitmap(contentPresenter, new TranslateTransform());

      contentImageChanged.Subscribe(
         contentImage => 
         {
            // Hide the content presenter now that we've taken a screen shot              
            contentPresenter.Visibility = Visibility.Collapsed; 

            // Set the image source of the image control to the snapshot
            contentImageControl.ImageSource = contentImage;
         });
   }

   // This method is invoked when the Content property is changed.
   protected override OnContentChanged(object oldContent, object newContent)
   {
      // show the content presenter before taking screenshot
      contentPresenter.Visibility = Visibility.Visible;  

      // raise the content changed "event"
      contentChanged.OnNext(newContent);   

      base.OnContentChanged(oldContent, newContent);
   }
}

这个例子特别简单,因为只有两个连续操作顺序。即使在这个简单的例子中,虽然我们可以看到Rx增加了价值。没有它,我不得不使用状态变量来确保事件以某种顺序触发。我也不得不从LayoutUpdated事件中写出一些非常丑的代码来显示分离。

This example is particularly simple given that there is only two consecutive operations to sequence. Even in this simple example though we can see that Rx adds value. Without it I would have had to have used state variables to ensure the events were firing in a certain order. I also would've had to write some pretty ugly code to explicity detach from the LayoutUpdated event.

当您使用Rx进行编程时,诀窍是想我希望我的框架提供什么事件?然后去创建它。我们受过训练,将事件作为简单的输入驱动的东西(鼠标悬停,mouseclick,keyup等)进行思考。但是,没有任何理由不能很复杂,特别是您的应用程序(GoogleMsdnMashupStockDataArrived,DragStarting和ImageContentChanged)。当您以这种方式构建程序时(创建完整的事件,我需要然后通过更改状态来响应),您会发现他们的状态错误更少,变得更加有序,并且更加自我 - 描述。

When you're programming with Rx the trick is to think "What event do I wish my framework provided?" and then go create it. We're trained to think about events as simple, input-driven things ("mouseover", "mouseclick", "keyup", etc). However there's no reason events can't be very complex and specific to your app ("GoogleMsdnMashupStockDataArrived", "DragStarting", and "ImageContentChanged"). When you structure your programs this way (create exactly the event I need and then respond to it by changing state) you'll find that they have fewer state bugs, become more ordered, and are altogether more self-describing.

知道了吗? :-)

这篇关于.NET Rx优于传统的事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆