使用 Rx,我有一个设置面板,它控制是否启用操作以及它们应该以什么速率运行。 这些存储在 LibrarySettings 类中,当通过前端 slider /复选框更改属性时,可观察属性会根据更改进行选择。
我应该如何编写 LibrarySettings 类,使其不会将 setting.Value(整个 LibrarySettings 实例)设置为 null。
IDisposable reader = setting.Value.Subscribe(options =>
{
OperationOneEnabled = options.OperationOneEnabled;
OperationTwoEnabled = options.OperationTwoEnabled;
OperationOneRate = options.OperationOneRate;
OperationTwoRate = options.OperationTwoRate;
});
IDisposable writer = this.WhenAnyPropertyChanged()
.Subscribe(vm =>
{
settings.Write(new LibrarySettings(OperationOneEnabled, OperationOneRate,
OperationTwoEnabled, OperationTwoRate));
});
OperationOneRateProperty = this.WhenValueChanged(vm => vm.ScheduleRate)
.DistinctUntilChanged()
.Select(value => $"{value} seconds")
.ForBinding();
_CleanUp = new CompositeDisposable(reader, writer, OperationOneRateProperty);
所以在 LibrarySettings 类中我需要能够创建属性
public IObservable<LibrarySettings> Value
{
get { return _Value; }
set { _Value = value; }
}
所以我尝试以下
Value = Observable.Create<LibrarySettings>(() =>
{
new LibrarySettings(false, OperationOneEnable,OperationOneRate,
OperationTwoEnabled, OperationTwoRate);
});
并得到一个
delegate func<IObserver<LibrarySettings>> does not take 0 arguments
最佳答案
首先,这不是有效代码(无法编译)
Value = Observable.Create<LibrarySettings>(() =>
{
new LibrarySettings(false, OperationOneEnable,OperationOneRate,
OperationTwoEnabled, OperationTwoRate);
});
Observable.Create 通常需要一个 Func<IObserver<T>, IDisposable>
作为参数,所以应该更正为
Value = Observable.Create<LibrarySettings>(observer =>
{
observer.OnNext(new LibrarySettings(/*args*/));
//What to do here?
return Disposable.Empty; //Yuck.
});
可能更好更简单的方法是使用 Observable.Return
,但是接下来可以观察到什么。似乎它使用 Rx 只是为了满足签名,因为这不符合 Rx 的精神。
相反,我想你真正想要的是 Settings
更改时推送通知的属性。为此我认为有两种合理的做法
- 您拥有
LibrarySettings
的只读属性类型LibrarySettings
在哪里是可变的和可观察的。 - 您有一个可变且可观察的属性
LibrarySettings
, 但类型LibrarySettings
是不可变的。
即要么是只读属性
this.Setting.WhenAnyPropertyChanged()....
this.Setting.OperationOneRate = 25;
this.Setting.IsOperationOneEnabled= true;
类型是可变的
public class LibrarySettings : INotifyPropertyChanged
{
public LibrarySettings()
{
IsOperationOneEnabled = false;;
OperationOneRate = 0;
IsOperationTwoEnabled = false;
OperationTwoRate = 0;
}
public bool IsOperationOneEnabled { get;set; }
public double OperationOneRate { get; set; }
public bool IsOperationTwoEnabled { get;set; }
public double OperationTwoRate { get; set;}
#region INPC Impl
#region
}
或者不可变类型,然后您改变属性(每次都使用一个新实例)。您显然希望使用默认值创建它。
this.WhenValueChanges(t=>t.Setting)....
this.Setting = new LibrarySettings(OperationOneEnable, OperationOneRate,
OperationTwoEnabled, OperationTwoRate);
还有像...这样的类型
public class LibrarySettings
{
public LibrarySettings(bool isOperationOneEnabled, double operationOneRate,
bool isOperationTwoEnabled, double operationTwoRate)
{
IsOperationOneEnabled = isOperationOneEnabled;
OperationOneRate = operationOneRate;
IsOperationTwoEnabled = isOperationTwoEnabled;
OperationTwoRate = operationTwoRate;
}
public bool IsOperationOneEnabled { get; }
public double OperationOneRate { get; }
public bool IsOperationTwoEnabled { get; }
public double OperationTwoRate { get;}
}
我刚刚找到您链接到的代码(您链接到 repo 的根而不是相关的实际类) * https://github.com/markiemarkus/Amadeus/blob/master/Amadeus/NovoApp/Models/LibrarySettings.cs
主要问题是这里的这些行
Value = Observable.Create<LibrarySettings>(observer =>
{
observer.OnNext(new LibrarySettings(false, OperationOneEnabled, OperationOneRate, OperationTwoEnabled, OperationTwoRate));
return Disposable.Empty;
});
public IObservable<LibrarySettings> Value
{
get { return _Value; }
set { _Value = value; }
}
public void Write(LibrarySettings item)
{
Value = Observable.Create<LibrarySettings>(observer =>
{
observer.OnNext(new LibrarySettings(false, OperationOneEnabled,
OperationOneRate, OperationTwoEnabled, OperationTwoRate));
return Disposable.Empty;
});
}
您创建了一个具有单个值的可观察序列(因此不是真正可观察的)。然后,您通过具有公共(public) setter 的属性公开它(可设置的 IObservable 属性是什么意思?!)。最后,您在写入方法中覆盖该实例,这意味着任何实际订阅了该属性原始值的人都将订阅一个孤立的 Observable 序列。
关于c# - 实现一个可观察的设置类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39327944/