2013-08-02 14 views
5

Ho un comportamento soggettoCome gestire eccezione su un argomento comportamento

var source = new BehaviorSubject<int>(0); 

Ho poi processo che fonte con qualcosa come

var withErrors = source 
      .Select(v => 
      { 
       if (v == 2) 
       { 
        throw new Exception("Ouch "); 
       } 
       return v; 
      }) 

Voglio iscrivermi a withErrors in modo tale che io può saltare gli errori . Un tentativo con cattura come questa.

public IObservabe<int> SkipError(IObservable<T> source){ 

    return source 
     .Catch(e=>SkipErrors(source.Skip(1)); 
} 

e quindi chiamare così

var withoutErrors = SkipError(withErrors); 

Skip è un tentativo di evitare di ripetere l'ultimo errore sul comportamento soggetto ma purtroppo non funziona in questo modo. Salta non salta gli errori ma solo su dati validi, quindi l'errore dallo stato corrente nel soggetto del comportamento continua a passare.

C'è un modo intelligente di scrivere Skip che salterà anche gli errori. Qualcosa mi dice che non è possibile, ma spero di sbagliarmi

+1

In realtà io sono giunto alla conclusione che questo è impossibile da raggiungere. Poiché secondo le specifiche RX un Observable non può continuare dopo aver chiamato OnError, non c'è nulla che tu possa fare per ottenere il valore successivo dopo che viene chiamato OnError. Avrò bisogno di inserire qualche logica nel punto in cui è stato generato l'errore. – bradgonesurfing

+1

corretto. La tua domanda è in conflitto con le specifiche Rx. Nota qui non è il BehaviorSubject ad avere errori, ma la proiezione (Seleziona operatore), non che ciò sia molto rilevante. –

+0

Ho capito che se desidero propagare errori come questo ho bisogno di IObservable > dove Eccezionale è definito come https://gist.github.com/bradphelan/6154972 ed è essenzialmente un contenitore che può contenere un'eccezione o un valore – bradgonesurfing

risposta

2

Come la premessa della domanda è errata, vi presento un modo di fare questo usando il better usando la monade Exceptional<T>. Per esempio

IObservable<int> source = ....; 
IObservable<Exceptional<string>> withErrors = 
    source.Select(i=>Exceptional.Execute(()=>{ 
     if(v==2){ 
      throw new Exception("Ouch"); 
     } 
     return v.ToString(); 
    }); 


IObservable<Exception> errors = 
    withErrors.Where(v=>v.HasException).select(v=>v.Exception); 

IObservable<string> values = 
    withErrors.Where(v=>!v.HasException).select(v=>v.Value); 

e solo per divertimento si può fare

Exceptional<string> r = 
     from x in Exceptional.Execute(() => "xxx") 
     from y in Exceptional.Execute(() => "zzz") 
     select x + y; 

che sarà la generazione di un eccezionale tenendo il valore "xxxzzz". Se uno qualsiasi dei passaggi genera un'eccezione, si verificherà un cortocircuito e manterrà solo l'eccezione.

mia implementazione basata fuori un altro SO risposta è https://gist.github.com/bradphelan/6154972

+0

sì, un modo per affrontare il problema è trasformare le eccezioni in dati. Un altro è catturare e consumare eccezioni senza farle scappare dal codice. Entrambi gli schemi ti consentono di decidere esattamente quali parti del tuo codice possono continuare a essere incorrotte se si verifica un'eccezione. – Brandon

Problemi correlati