2017-09-21 2 views
2

Comment faire passer ce test sans utiliser la classe Subject ou .NET events?Comment créer un IObservable qui émet lors d'un appel de méthode, sans utiliser de Sujets ou d'événements .NET?

[TestClass] 
public class ObservableTests 
{ 
    private readonly Subject<Unit> _subject = new Subject<Unit>(); 

    [TestMethod] 
    public void ObservesMethodCall() 
    { 
     var eventCount = 0; 
     IObservable<Unit> observable = _subject.AsObservable(); 
     observable.Subscribe(u => eventCount++); 

     Assert.AreEqual(0, eventCount); 
     Foo(); 
     Assert.AreEqual(1, eventCount); 
    } 

    private void Foo() 
    { 
     _subject.OnNext(Unit.Default); 
    } 
} 

Je veux éviter d'utiliser subjects comme they are not recommended. Je ne veux pas utiliser les événements .NET lorsque RxNet les remplace.

questions connexes:

Firing an event every time a new method is called
Il suppose que nous ne pouvons pas modifier la méthode appelée.

How to create Observable that emits every time a member variable is updated (onCompleted never called)
Utilise des sujets.

Is there a way to create an observable sequence triggered by method calls without using Subject?
États Les sujets sont la voie à suivre. Cependant, je veux toujours apprendre comment le faire sans Sujets.

IObserver and IObservable in C# for Observer vs Delegates, Events
Indique comment résoudre le problème en mettant en œuvre la coutume IObservable

Répondre

3

Cela pourrait être un peu comme couper les cheveux, mais cela fonctionne sans avoir besoin d'un sujet:

[TestClass] 
public class ObservaleTests 
{ 
    private Action _action = null; 

    [TestMethod] 
    public void ObservesMethodCall() 
    { 
     var eventCount = 0; 

     IObservable<Unit> observable = 
      Observable.FromEvent(a => _action += a, a => _action -= a); 

     observable.Subscribe(u => eventCount++); 

     Assert.AreEqual(0, eventCount); 
     Foo(); 
     Assert.AreEqual(1, eventCount); 
    } 

    private void Foo() 
    { 
     _action(); 
    } 
} 
+0

Pouvez-vous expliquer comment cela fonctionne? – VMAtm

+0

@VMAtm - De quel bit n'êtes-vous pas sûr? Le 'FromEvent'? – Enigmativity

+0

Oui, je ne comprends pas la duplication là. – VMAtm

0

En bref, vous voulez déclencher un observable de manière procédurale, mais sans utiliser de sujets ou d'événements. Vous pouvez utiliser un délégué personnalisé (réponse de @ Enigmativity), et vous pouvez également implémenter IObservable personnalisé (essentiellement en réinventant des sujets).

Je vais contester le principe cependant: Utilisez un sujet. Ils ne sont pas toujours recommandés, mais ils conviennent à votre problème artificiel tel que présenté. La plus grande question que vous devriez poser cependant est pourquoi vous voulez déclencher une observable procéduralement: Le but entier de System.Reactive est que vous pouvez juste vous inquiéter d'un côté d'un message: Soit le récepteur (observable) ou l'expéditeur (observateur). Vous essayez de faire les deux, ce qui est un sujet. Le problème avec Subjects n'est pas une sorte de détail d'implémentation, ou de dogme (Subjects bad, Observables good), c'est que le but est simplement de se concentrer sur la réception des messages, pas sur l'envoi et la réception.

+0

Le problème n'est pas artificiel. C'est l'un des cas d'utilisation les plus simples et les plus courants: "Je veux observer les appels de méthode, comment puis-je le faire?". Plus concrètement, j'écris une classe qui déclenche quelque chose et je veux exposer de telles occurrences de déclenchement comme IObservable dans cette interface de classe. –

+0

Le problème tel que présenté est artificiel: Vous voulez essentiellement un sujet, sans utiliser 'Subject '. Je vous suggère de lire quelques-unes des réponses liées à * pourquoi * un «sujet» n'est pas recommandé. Vous remarquerez que ce sont vraiment les dessins qui ont tendance à se former autour de "Sujet" qui ne sont pas recommandés, pas la classe elle-même. – Shlomo

+0

Il ya un saut trop grand pour moi de "Je veux exposer les appels de méthode comme IObservable" à "vous voulez essentiellement un sujet, donc votre problème est artificiel".Dave Sexton's "Pour utiliser le sujet ou ne pas utiliser le sujet?" article semble dire que les sujets sont en effet la bonne approche pour ce scénario, mais l'explication est loin d'être triviale. –