RX - 可以/我应该替换观测量.NET事件? [英] Rx - can/should I replace .NET events with Observables?

查看:114
本文介绍了RX - 可以/我应该替换观测量.NET事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于组合的活动带来的好处由反应扩展(接收)框架的提供,我想知道我的课是否应该停止推动.NET的事件,而是揭露接收观测



例如,使用标准的.NET事件采取以下类:

 公共类Foo 
{
私人诠释的进展情况;
公共事件的EventHandler ProgressChanged;

公众诠释进展
{
{返回this.progress; }

{
如果(this.progress =价值!)
{
this.progress =价值;

//同时检查没有订户和预防退订竞争条件引发事件。
VAR progressChanged = this.ProgressChanged;
如果(progressChanged!= NULL)
{
progressChanged(在此,新的EventArgs());
}
}
}
}
}


$ B $单调水暖乙

地块。



本类可以代替使用某种观察到的替换该功能:

 公共类Foo 
{
公共美孚()
{
this.Progress =一些新的观察到;
}

公众的IObservable< INT> {进展得;私人集; }
}



远不如管道。目的是通过管道细节不再模糊。这似乎是有利的。



我对你罚款StackOverflow的人的问题是:




  1. 会是好/值得替换的IObservable<标准.NET事件; T>值?

  2. 如果我是使用可观察到的,什么样的我会用在这里?很显然,我需要把值给它(例如Progress.UpdateValue(...)或东西)。


解决方案

我不建议当管理有建于学科,可以为你做你自己的订户名单。它也消除了携带的T自己的可变副本需要



下面是我的(commentless)版本的解决方案:

 公共类观测< T> :&的IObservable LT;吨>中INotifyPropertyChanged的
{
私人只读BehaviorSubject< T>值;

私人PropertyChangedEventHandler的PropertyChanged;

公众观测():这个(默认值(T))
{
}

公众观测(T initalValue)
{
this.values​​ =新BehaviorSubject< T>(initalValue);

values​​.DistinctUntilChanged()订阅(FirePropertyChanged);
}

公众吨价
{
{返回this.values​​.First(); }
集合{values​​.OnNext(值); }
}

私人无效FirePropertyChanged(T值)
{
VAR处理器= this.propertyChanged;

如果(处理!= NULL)
处理器(这一点,新PropertyChangedEventArgs(值));
}

公共重写字符串的ToString()
{
返回值!= NULL? value.ToString():可观察到的与所述;​​ +的typeof(T),请将.Name +>在空值。
}

公共静态隐运营商T(可观察到的LT&; T>输入)
{
返回input.Value;
}

公共IDisposable的订阅(IObserver< T>观察员)
{
返回values​​.Subscribe(观察员);
}

事件PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
加{this.propertyChanged + =价值; }
拆下{this.propertyChanged - =价值; }
}
}


Given the benefits of composable events as offered by the Reactive Extensions (Rx) framework, I'm wondering whether my classes should stop pushing .NET events, and instead expose Rx observables.

For instance, take the following class using standard .NET events:

public class Foo
{
   private int progress;
   public event EventHandler ProgressChanged;

   public int Progress
   {
      get { return this.progress; }
      set
      {
         if (this.progress != value)
         {
            this.progress = value;

            // Raise the event while checking for no subscribers and preventing unsubscription race condition.
            var progressChanged = this.ProgressChanged;
            if (progressChanged != null)
            {
                progressChanged(this, new EventArgs());
            }
         }
      }
   }
}

Lot of monotonous plumbing.

This class could instead use some sort of observable to replace this functionality:

public class Foo
{
   public Foo()
   {
       this.Progress = some new observable;
   }

   public IObservable<int> Progress { get; private set; }
}

Far less plumbing. Intention is no longer obscured by plumbing details. This seems beneficial.

My questions for you fine StackOverflow folks are:

  1. Would it good/worthwhile to replace standard .NET events with IObservable<T> values?
  2. If I were to use an observable, what kind would I use here? Obviously I need to push values to it (e.g. Progress.UpdateValue(...) or something).

解决方案

I don't recommend managing your own subscriber list when there are built in subjects that can do that for you. It also removes the need for carrying your own mutable copy of T.

Below is my (commentless) version of your solution:

public class Observable<T> : IObservable<T>, INotifyPropertyChanged 
{ 
    private readonly BehaviorSubject<T> values; 

    private PropertyChangedEventHandler propertyChanged; 

    public Observable() : this(default(T))
    {
    } 

    public Observable(T initalValue) 
    { 
        this.values = new BehaviorSubject<T>(initalValue);

        values.DistinctUntilChanged().Subscribe(FirePropertyChanged);
    }

    public T Value 
    { 
        get { return this.values.First(); } 
        set { values.OnNext(value); } 
    }

    private void FirePropertyChanged(T value)
    {
        var handler = this.propertyChanged;

        if (handler != null)
            handler(this, new PropertyChangedEventArgs("Value"));
    }

    public override string ToString() 
    { 
        return value != null ? value.ToString() : "Observable<" + typeof(T).Name + "> with null value."; 
    } 

    public static implicit operator T(Observable<T> input) 
    { 
        return input.Value; 
    } 

    public IDisposable Subscribe(IObserver<T> observer) 
    { 
        return values.Subscribe(observer);
    } 

    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged 
    { 
        add { this.propertyChanged += value; } 
        remove { this.propertyChanged -= value; } 
    } 
}

这篇关于RX - 可以/我应该替换观测量.NET事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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