我最喜欢的“优雅”方式是使用可观察对象而不是事件,尤其是在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
lambda 在这里是自定义扩展方法的一个参数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