附加两个 ReactiveProperty 的更好方法
Better way to attach two ReactiveProperty
我在我的代码中使用 ReactiveProperty 库,有时我需要将两个 ReactiveProperty<T>
连接在一起以保持 属性 数据同步。例如,通过将服务 class 中的 ReactivePropertySlim
组合到 ViewModel class.
中的 ReactiveProperty
通常我使用下一个代码:
// NewProperty is a ViewModel public property
NewProperty = service.Property.ToReactiveProperty<T>();
var propertyDisposable = NewProperty.Subscribe(value => service.Property.Value = value);
单个 属性 的查找不是那么糟糕,但是当数字变大时,代码就会到达。
目前我使用简单的扩展方法来限制代码重复。
public static (IReactiveProperty<T> property, IDisposable cleanup) AttachReactiveProperty<T>(this IReactiveProperty<T> baseProperty)
{
var newProperty = baseProperty.ToReactiveProperty<T>();
var cleanup = newProperty.Subscribe(value => baseProperty.Value = value);
return (newProperty, cleanup);
}
我以一个 属性 变量和一个 IDisposable 变量结尾来管理退订。
var (pausedProperty, pausedDisposable) = remoteConversion.Paused.AttachReactiveProperty();
NewProperty = pausedProperty;
现在扩展正在做他的工作(我认为代码更少更清晰)。但是有没有更好的方法来解决这个问题。
好吧,我找到了一个类似但更干净(我认为)的方法。
在每个反应式 classes 中,我通常有一些像这样的 CompositeDisposable _cleanup
字段。
public sealed class SomeClass: IDisposable
{
private readonly CompositeDisposable _cleanup = new CompositeDisposable();
public void Dispose()
{
_cleanup.Dispose();
}
}
然后使用这个基本的class构造和这个扩展方法
internal static class ReactivePropertyEx
{
public static IReactiveProperty<T> AttachReactiveProperty<T>(this IReactiveProperty<T> baseProperty, Action<IDisposable> registerDisposable)
{
var newProperty = baseProperty.ToReactiveProperty<T>();
var cleanup = newProperty.Subscribe(value => baseProperty.Value = value);
registerDisposable(cleanup);
return newProperty;
}
}
代码结束更简洁优雅。用法是
NewProperty = service.Property.AttachReactiveProperty(disposable => disposable.AddTo(_cleanup));
在这种情况下,您可以使用在 Reactive.Bindings.Extensions
命名空间中定义的 ToReactiveProperty[Slim]AsSynchronized
扩展方法。
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
var rp1 = new ReactiveProperty<string>("Init");
ReactiveProperty<string> rp2 = rp1.ToReactivePropertyAsSynchronized(x => x.Value);
ReactivePropertySlim<string> rp3 = rp1.ToReactivePropertySlimAsSynchronized(x => x.Value);
Console.WriteLine("----");
Console.WriteLine(rp1.Value); // Init
Console.WriteLine(rp2.Value); // Init
Console.WriteLine(rp3.Value); // Init
rp1.Value = "Update from rp1";
Console.WriteLine("----");
Console.WriteLine(rp1.Value); // Update from rp1
Console.WriteLine(rp2.Value); // Update from rp1
Console.WriteLine(rp3.Value); // Update from rp1
rp3.Value = "Update from rp3";
Console.WriteLine("----");
Console.WriteLine(rp1.Value); // Update from rp3
Console.WriteLine(rp2.Value); // Update from rp3
Console.WriteLine(rp3.Value); // Update from rp3
// disconnect
rp2.Dispose();
rp3.Dispose();
rp1.Value = "Done";
Console.WriteLine("----");
Console.WriteLine(rp1.Value); // Done
Console.WriteLine(rp2.Value); // Update from rp3
Console.WriteLine(rp3.Value); // Update from rp3
我在我的代码中使用 ReactiveProperty 库,有时我需要将两个 ReactiveProperty<T>
连接在一起以保持 属性 数据同步。例如,通过将服务 class 中的 ReactivePropertySlim
组合到 ViewModel class.
ReactiveProperty
通常我使用下一个代码:
// NewProperty is a ViewModel public property
NewProperty = service.Property.ToReactiveProperty<T>();
var propertyDisposable = NewProperty.Subscribe(value => service.Property.Value = value);
单个 属性 的查找不是那么糟糕,但是当数字变大时,代码就会到达。
目前我使用简单的扩展方法来限制代码重复。
public static (IReactiveProperty<T> property, IDisposable cleanup) AttachReactiveProperty<T>(this IReactiveProperty<T> baseProperty)
{
var newProperty = baseProperty.ToReactiveProperty<T>();
var cleanup = newProperty.Subscribe(value => baseProperty.Value = value);
return (newProperty, cleanup);
}
我以一个 属性 变量和一个 IDisposable 变量结尾来管理退订。
var (pausedProperty, pausedDisposable) = remoteConversion.Paused.AttachReactiveProperty();
NewProperty = pausedProperty;
现在扩展正在做他的工作(我认为代码更少更清晰)。但是有没有更好的方法来解决这个问题。
好吧,我找到了一个类似但更干净(我认为)的方法。
在每个反应式 classes 中,我通常有一些像这样的 CompositeDisposable _cleanup
字段。
public sealed class SomeClass: IDisposable
{
private readonly CompositeDisposable _cleanup = new CompositeDisposable();
public void Dispose()
{
_cleanup.Dispose();
}
}
然后使用这个基本的class构造和这个扩展方法
internal static class ReactivePropertyEx
{
public static IReactiveProperty<T> AttachReactiveProperty<T>(this IReactiveProperty<T> baseProperty, Action<IDisposable> registerDisposable)
{
var newProperty = baseProperty.ToReactiveProperty<T>();
var cleanup = newProperty.Subscribe(value => baseProperty.Value = value);
registerDisposable(cleanup);
return newProperty;
}
}
代码结束更简洁优雅。用法是
NewProperty = service.Property.AttachReactiveProperty(disposable => disposable.AddTo(_cleanup));
在这种情况下,您可以使用在 Reactive.Bindings.Extensions
命名空间中定义的 ToReactiveProperty[Slim]AsSynchronized
扩展方法。
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
var rp1 = new ReactiveProperty<string>("Init");
ReactiveProperty<string> rp2 = rp1.ToReactivePropertyAsSynchronized(x => x.Value);
ReactivePropertySlim<string> rp3 = rp1.ToReactivePropertySlimAsSynchronized(x => x.Value);
Console.WriteLine("----");
Console.WriteLine(rp1.Value); // Init
Console.WriteLine(rp2.Value); // Init
Console.WriteLine(rp3.Value); // Init
rp1.Value = "Update from rp1";
Console.WriteLine("----");
Console.WriteLine(rp1.Value); // Update from rp1
Console.WriteLine(rp2.Value); // Update from rp1
Console.WriteLine(rp3.Value); // Update from rp1
rp3.Value = "Update from rp3";
Console.WriteLine("----");
Console.WriteLine(rp1.Value); // Update from rp3
Console.WriteLine(rp2.Value); // Update from rp3
Console.WriteLine(rp3.Value); // Update from rp3
// disconnect
rp2.Dispose();
rp3.Dispose();
rp1.Value = "Done";
Console.WriteLine("----");
Console.WriteLine(rp1.Value); // Done
Console.WriteLine(rp2.Value); // Update from rp3
Console.WriteLine(rp3.Value); // Update from rp3