2011-11-14 17 views
6

Ho un evento che non ho il controllo di cui mi fornisce i dati. I eventArgs simile a questa:Come completare un Rx Osservabile a seconda di una condizione in un evento

class MyEventArg { 
    bool IsLastItem {get;} 
    Data DataItem {get;} 
} 

Io uso Rx per convertire questo evento per un IObservable. Ma voglio completare l'osservabile se IsLastItem è vero.

Qualche idea elegante? Un modo potrebbe essere quello di pipa i dati attraverso un argomento che ho più controllo sulle impostare l'evento OnComplete se si verifica la condizione ...

risposta

9

Se si desidera che l'ultimo elemento da inserire è possibile unire un ruscello con solo l'ultimo elemento insieme al regolare flusso combinato con TakeWhile. Ecco una semplice console app per dimostrarlo:

var subject = new List<string> 
{        
"test", 
"last" 
}.ToObservable(); 

var my = subject 
      .Where(x => x == "last").Take(1) 
      .Merge(subject.TakeWhile(x => x != "last")); 

my.Subscribe(
    o => Console.WriteLine("On Next: " + o), 
    () => Console.WriteLine("Completed")); 

Console.ReadLine(); 

Questo stampa:

On Next: test 
On Next: last 
Completed 

UPDATE C'era un bug che soppressa il messaggio OnCompleted se osservabile sottostante non ha effettivamente completa . Ho corretto il codice per garantire OnCompleted viene chiamato

E se si vuole evitare la sottoscrizione alla sequenza sottostante più volte per osservabili a freddo si può refactoring del codice come questo:

var my = subject.Publish(p => p 
      .Where(x => x == "last").Take(1) 
      .Merge(p.TakeWhile(x => x != "last"))); 
+0

Bello! Mi ci sono voluti alcuni secondi per vedere come è fatto. Forse scrivere meglio: subject.TakeWhile (x => x! = "Last"). Unisci (subject.Where (x => x == "last"). Take (1)); La punta fredda osservabile è un +. Grazie – lukebuehler

2

Siete alla ricerca di qualcosa di simile?

IObservable<MyEventArg> result = 
    myEventArgObservable.TakeWhile(arg => !arg.IsLastItem); 
+0

Wow, che avrebbe semplice e carino Sai se l'Osservabile si completa se il predicato è vero? – lukebuehler

+0

Sì, ne informa OnCompleted() se non si vuole che notifica OnCompleted si può semplicemente utilizzare Dove (arg =>! Arg.IsLastItem) – Christoph

+1

Sì, sembra che il completamento del osservabili, ma ora ho il problema che Non riceverò l'ultimo oggetto ... – lukebuehler

2
public static IObservable<TSource> TakeWhileInclusive<TSource>(
     this IObservable<TSource> source, Func<TSource, bool> predicate) 
{ 
    return Observable 
     .Create<TSource>(o => source.Subscribe(x => 
                { 
                 o.OnNext(x); 
                 if (!predicate(x)) 
                  o.OnCompleted(); 
                }, 
               o.OnError, 
               o.OnCompleted 
           )); 
} 
Problemi correlati