2014-06-26 28 views
1

假設我想公開一個可立即通知的可觀察事件,如果Internet連接現在可用,或者設備未連接到Internet,通知將被推出時,它確實可用:可觀察到每訂閱產生一個項目 - 每個處理程序產生一個事件

IObservable<DateTime> InternetBecameAvailableSignalledOncePerSubscriber { get; } 

而且,應該是每股認購只有一個通知,而無需用戶做。取(1)或類似的東西。

即依賴於互聯網資源的客戶端將使用此可觀察項目立即執行某項操作,或者一旦互聯網變得可用,但不會多次執行此操作 - 如果該用戶沒有更多信令,互聯網變得不可用並且第二次可用。

這怎麼可以用反應性擴展(Rx)實現?

  • 請忽略有缺陷的概念,互聯網可以成爲可用這樣的,認爲它是google.com可到達或任何口味的實現你喜歡
+0

你可以用.Aggregate做到這一點 - 但在這種情況下,我會建議書面方式自己的類/包裝,你可能想要控制的訂閱prozess好一點 – Carsten

+0

你可以絕對使用Rx做到這一點,但是當只有一個通知時,異步方法更容易。 –

回答

1

這應當其中Rx迎刃而解。問題是如何知道互聯網是否可用?它是基於其他消費者訂閱,是基於另一種方法(如Connect()方法)還是某些正在推送給您的事件(如WCF頻道狀態更改事件)?

根據這個答案,你似乎只需要封裝你的Take(1)和Replay(1)。

public class IServiceClient 
{ 
    IObservable<DateTime> LastConnnected { get; } 
} 

public class ServiceClient : IServiceClient, IDisposable 
{ 
    private readonly IDisposable _connection; 
    private readonly IObservable<DateTime> _lastConnnected; 

    public ServiceClient() 
    { 
     //Question 1) where does the 'Connected' sequence come from i.e. what is it that tells you that you have internet connectivity? 
     //Question 2) When should the subscription be made to 'Connected'? Here I cheat and do it in the ctor, not great. 
     var connected = Connected.Replay(1) 
           .Where(isConnected=>isConnected) 
           .Take(1) 
           .Select(_=>DateTime.UtcNow); 

     _lastConnnected = connected; 
     _connection = connected.Connect(); 
    } 

    public IObservable<DateTime> LastConnnected{ get {return _lastConnnected; } } 

    public void Dispose() 
    { 
     _connection.Dispose(); 
    } 
} 

這確實會給你一些其他問題以回答例如什麼是告訴你,如果你有互聯網連接和什麼資源管理計劃呢?

更新代碼

public interface IServiceClient 
{ 
    IObservable<DateTime> LastConnnected { get; } 
} 

public class ServiceClient : IServiceClient, IDisposable 
{ 
    private readonly IDisposable _connection; 
    private readonly IObservable<bool> _lastConnnected; 

    public ServiceClient(IObservable<ConnectionState> connectedStates) 
    { 
     var cachedStates = connectedStates.Select(state=>state.IsConnected).Replay(1); 
     _lastConnnected = cachedStates; 
     _connection = cachedStates.Connect(); 
    } 

    public IObservable<DateTime> LastConnnected 
    { 
     get 
     { 
      return _lastConnnected.StartWith(IsConnected()) 
            .Where(isConnected=>isConnected) 
            .Take(1) 
            .Select(_=>DateTime.UtcNow); 
     } 
    } 

    //.... 

    public void Dispose() 
    { 
     _connection.Dispose(); 
    } 
} 
+0

謝謝!我有一個方法bool IsConnected(),可以用來查看是否應該立即推送一個值,如果這是錯誤的,那麼我有一個熱的IObservable 流斷開連接狀態 - 我不是很熟悉可連接的可觀測量,那麼給定這個源方法和序列的代碼應該如何改變? – Cel

+1

這裏我們說我們想重放1個值,所以它應該緩存它看到的最後一個值。但是,這需要訂閱才能做到這一點。在這種情況下,我們「連接」來調用訂閱並開始緩存值。在你的情況下,這不會做太多,因爲你的序列已經很熱。代碼已更新 –

相關問題