私のお気に入りの「エレガントな」方法は、特にReactive Extensionsの助けを借りて実装された、イベントの代わりにオブザーバブルを使用することです。そうすることができると想像してください:
class SomeClass
{
public ObservableProperty<double> SomeDouble { get; private set; }
public SomeClass()
{
SomeDouble = new ObservableProperty<double>();
}
}
class Program
{
static void Main(string[] args)
{
SomeClass someobject = new SomeClass();
const double lam = 1.0;
using (var sub = someobject.SomeDouble.Observable
.TakeWhile((oldvalue, newvalue) =>
Math.Abs(oldvalue - newvalue) > lam)
.Subscribe(x =>
Console.WriteLine("{0}\t{1}",x,someobject.SomeDouble.Value)))
{
someobject.SomeDouble.Value = 3.0;
someobject.SomeDouble.Value = 2.0;
someobject.SomeDouble.Value = 1.0;
someobject.SomeDouble.Value = -1.0;
}
}
}
出力で
3 3
1 1
-1 -1
ラムダは、カスタム拡張メソッドのパラメーターですTakeWhile
。
観察可能なプロパティのラッパーは次のようになります (完全ではない可能性があります)。
/// Wrapper for properties that notify their change by means of an observable sequence
class ObservableProperty<T>
{
T val;
ISubject<T> sub = new Subject<T>();
public T Value
{
get { return val; }
set
{
val = value;
sub.OnNext(value);
}
}
public IObservable<T> Observable
{
get { return sub; }
}
}
カスタム拡張メソッドは次のとおりです。
public static class Extensions
{
/// Return distinct values from source while AdjacentCompare is true
public static IObservable<TSource> TakeWhile<TSource>(this IObservable<TSource> source, Func<TSource, TSource, bool> AdjacentCompare)
{
return source.Scan((oldvalue, newvalue) =>
{
if (AdjacentCompare(oldvalue, newvalue))
return newvalue;
return oldvalue;
}).DistinctUntilChanged();
}
}
ヘルパー クラスと拡張メソッドは比較的長く見える場合がありますが、これらは一般的なものです。つまり、値を比較する方法やそれらの型 (おそらく実装によって制限される) は問題ではなく、rx の利点が得られます。サブスクリプションの有効期間を簡単に制御し、スレッド セーフを実現し、宣言型コードを記述します。
少し前に検索中に、このライブラリに出くわしました: ReactiveProperty