2016-09-05 98 views
1

使用Rx,我有一個設置面板,用於控制是否啓用操作以及應該運行的速率。 這些存儲在LibrarySettings類中,當通過前端滑塊/複選框對屬性進行更改時,observable屬性會根據更改進行選擇。實現可觀察的設置類

我該如何編寫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

+0

你爲什麼認爲setting.Value將變爲null? –

+0

@BuhBuh 當LibrarySettings類第一次啓動時,它爲null。即'新的LibrarySettings(true,20,true,30)'這些已啓用並設置了費率屬性,但值不是 – Mdev

+0

您是否使用ReactiveUI? – Shlomo

回答

2

首先,這是無效的代碼(慣於編譯)

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;} 
} 

我剛剛發現,你鏈接到(你鏈接到回購的根沒有問題的實際類) * 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; 
    }); 
} 

您創建一個具有單一值的可觀察序列(這樣是不是真的觀察到)。然後通過一個公共setter將它暴露出來(可設置的IObservable屬性是什麼意思?!)。最後,您在寫入方法中寫入該實例,意味着實際訂閱了該屬性原始值的任何人都將持有對孤立Observable序列的訂閱。

1

如果你只是希望讓過去的編譯錯誤,你會用這場比賽的勝利:

Value = Observable.Return(new LibrarySettings(/*args*/)); 

或本:

Value = Observable.Create<LibrarySettings>(observer => 
{ 
    observer.OnNext(new LibrarySettings(/*args*/)); 
    return Disposable.Empty; 
}); 

這聽起來像你有一個更大的設計問題你還沒有佈置。

+0

請查看https://github.com/markiemarkus/Amadeus---Copy 但是,這是一個勝利,以通過編譯錯誤 – Mdev

+0

返回'Disposable.Empty'是如此糟糕的反模式。我強烈建議OP,他們避免這個特殊的'Observable.Create'變種。 – Enigmativity

+0

爲什麼反模式?這兩者在功能上等同。 – Shlomo