问题
Say I have a factory method that churns out instances of type T, and I want an Rx observable sequence for events fired from all my instances originating out of the factory method.
Is using Merge() as I have done below the correct and optimal way to achieve this?
The other way I did this was to use a static event and make the observable sequence out of that, however I generally don't like using static events and am curious what any Rx experts think would be optimal in this situation?
public T MakeFoo<T>() where T: Foo, new()
{
this.instanceOfObservable.Merge(new T());
return self;
}
public class ObservableSequence : IObservable<EventArgs>, IDisposable
{
private IObservable<EventArgs> stream;
public ObservableSequence()
{
}
// this method is called in the factory method for each new instance of T
public void Merge(Foo instance)
{
if (this.stream == null)
{
this.stream = Init(instance);
}
else
{
IObservable<EventArgs> next = Init(instance);
this.stream.Merge(next);
}
}
private IObservable<EventArgs> Init(Foo instance)
{
return Observable.FromEvent
<EventHandler<EventArgs>, EventArgs>(handler =>
{
EventHandler<EventArgs> eh = (sender, e) => {
handler(e);
};
return eh;
},
eh => instance.SomeEvent += eh ,
eh => instance.SomeEvent -= eh )
.Repeat()
.Retry()
.Publish()
.RefCount();
}
public void Dispose()
{
}
public IDisposable Subscribe(IObserver<EventArgs> observer)
{
return stream.Subscribe(observer);
}
}
回答1:
Abusing Merge
like that is not very efficient. The most straightforward way is via a Subject, which is an IObservable you control by hand.
public static class MyAwesomeFooFactory
{
readonly static Subject<SomeEventArgs> someEvents = new Subject<SomeEventArgs>();
public static IObservable<SomeEventArgs> NotificationsFromAllTheEvents { get { return someEvent; }}
public static Foo MakeANewFoo()
{
var ret = new Foo();
ret.SomeEvent.Subscribe(someEvents); // NB: We never unsubscribe, *evar*
return ret;
}
}
回答2:
That is unlikely to work as you want, and has potentially stack-breaking performance issues. For every instance you add, you add another call to the stack between the first instance and the final observer. Get too many instances and you could blow the stack.
More important is the potentially wrong functionality. Does an observer expect to get notifications from all Foo
s created after it subscribes? In your current design they will not. If they should get notifications, you should change stream
to a Subject<EventArgs>
and have it subscribe to each Foo
. The subject will serve as a merge point with the benefit that all of the subscribers to the subject will get the messages from instances created after the observer subscribed.
来源:https://stackoverflow.com/questions/8980014/correct-way-to-merge-observable-sequences-for-events-fired-from-multiple-instanc