.NET 4.0 ベータ 2では、IObservableおよびIObserverインターフェイスが導入されました。
従来の .NET イベントと比べてどのような利点がありますか? これで同じ問題が解決しませんか?
.NET 4.0 ベータ 2では、IObservableおよびIObserverインターフェイスが導入されました。
従来の .NET イベントと比べてどのような利点がありますか? これで同じ問題が解決しませんか?
IObservableをイベントとして使用して、イベントを公開するコードをIObservableタイプのプロパティに置き換えることができますが、それは実際には重要ではありません。
IObservableについて理解しておくべき2つの重要なことがあります。
これは、以前は統合する方法がわからなかった2つの概念を統合します。非同期操作(通常は単一の値を返す)とイベント(通常は永久に続く)です。
構成可能です。CLRイベント、IAsyncResult、またはINotifyCollectionChangedとは異なり、一般的なイベントと非同期操作から特定のイベントを構築できます。
これが私が今日の午後仕事で出くわした例です。
Silverlightには、通常のコントロールには適用できない画像コントロールに適用できるいくつかの効果があります。コントロールのコンテンツが変更されたときにこれらの制限を回避するために、外観が更新されるのを待って、スクリーンショットを撮ることができます。次に、その視覚的表現を非表示にし、スナップショットに置き換えて、視覚効果を画像に適用します。これで、画像効果をコントロールに適用できます(インタラクティブではないと仮定します)。
このプログラムは簡単ですが、非同期でなければならないという事実のためです。画像に効果を適用する前に、2つの連続する非同期操作が完了するのを待つ必要があります。
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);
}
}
この例は、シーケンスする操作が2つしかないため、特に単純です。この単純な例でも、Rxが付加価値をもたらすことがわかります。それがなければ、イベントが特定の順序で発生することを保証するために状態変数を使用する必要がありました。また、LayoutUpdatedイベントから明示的に切り離すために、かなり醜いコードを作成する必要がありました。
Rxを使用してプログラミングする場合の秘訣は、「フレームワークを提供したいイベントは何ですか?」と考えることです。そしてそれを作成しに行きます。私たちは、イベントを単純な入力駆動型のもの(「マウスオーバー」、「マウスクリック」、「キーアップ」など)として考えるように訓練されています。ただし、イベントが非常に複雑でアプリに固有である可能性がある理由はありません( "GoogleMsdnMashupStockDataArrived"、 "DragStarting"、および "ImageContentChanged")。プログラムをこのように構成すると(必要なイベントを正確に作成し、状態を変更してそれに応答する)、状態のバグが少なくなり、順序が決まり、全体として自己記述的であることがわかります。
とった?:-)
利点はよくわかりませんが、従来の .NET イベントには次のような違いがあります。
エラー通知
クラシック イベントでは、このために別のイベントが必要になるか、チェックする必要がEventArgs
あるプロパティを持つクラスが必要になります。Error
通知終了通知
従来のイベントでは、これに対して別のイベントが必要になるか、チェックする必要がEventArgs
あるプロパティを持つクラスが必要になります。Final
これは、イベント ベースのプログラミング モデルの単なる拡張です。IObserver を実装するものを作成し、基本的には「コレクション内の何かが変更されたときに発生したいことは次のとおりです」と言っています。そういう意味では、これは私たち全員がイベントで行ってきたことの標準化にすぎません。
彼らは、IEnumerable パターンと比較して、大きな方向転換のようにそれを推し進めています。IEnumerable は「プル」ですが、IObservable は「プッシュ」です。
ストレート イベントよりも優れている点は、インターフェイスが標準化されていることだけです。ただし、ここでは ObservableCollection (および INotifyCollectionChanged) との大きな重複が見られます。おそらく、彼らは .NET で PERL のモットーを採用しようとしているのでしょう。「それを行うには複数の方法があります」。
Rx Workshop:Observables vs Eventsビデオを必ず見て、添付のチャレンジを完了する必要があります