c# - 实现一个可观察的设置类

标签 c# system.reactive reactive-programming

使用 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更改时推送通知的属性。为此我认为有两种合理的做法

  1. 您拥有 LibrarySettings 的只读属性类型 LibrarySettings 在哪里是可变的和可观察的。
  2. 您有一个可变且可观察的属性 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/

相关文章:

c# - 如何使用 Rx 从 SerialPort 读取数据的 "reconstruct lines"

system.reactive - 为什么 RX 中的主题称为 "Subject"?

c# - 我在 ToolStripSeparator c# 中看不到 RenderMode-property

c# - 如何在 Azure 搜索中允许自定义分析器使用通配符

c# - 来自字符串、整数等的枚举

akka - 如何使用 Socko 网络服务器实现 OpenID 依赖方?

swift - RxSwift flatMap 最新一次无需处理

c# - 如何在 .NET 中获取 pdf 文档中页面的方向?

c# - 为什么 RX 不在新线程上运行处理程序?

c# - 如何使用 List<> 阻止 ToObservable?