Правильный способ объединения наблюдаемых последовательностей для событий, запущенных из нескольких экземпляров - PullRequest
2 голосов
/ 24 января 2012

Скажем, у меня есть фабричный метод, который производит экземпляры типа T, и я хочу, чтобы наблюдаемая последовательность Rx для событий, запущенных из всех моих экземпляров, происходящих из фабричного метода.

Использует ли Merge (), как я сделал ниже, правильный и оптимальный способ достижения этого?

Другой способ, которым я это сделал, - использовать статическое событие и сделать из него наблюдаемую последовательность, однако мне обычно не нравится использовать статические события, и мне любопытно, что по мнению экспертов Rx будет оптимальным в этомситуация?

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);
    }
}

Ответы [ 2 ]

2 голосов
/ 24 января 2012

Злоупотребление Merge как это не очень эффективно. Самый простой способ - через субъект, который является IObservable, которым вы управляете вручную.

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;
    }
}
1 голос
/ 24 января 2012

Это вряд ли будет работать так, как вы хотите, и может привести к потере производительности. Для каждого добавляемого вами экземпляра вы добавляете еще один вызов в стек между первым экземпляром и конечным наблюдателем. Получить слишком много экземпляров, и вы можете взорвать стек.

Более важной является потенциально неправильная функциональность. Ожидает ли наблюдатель получать уведомления от всех Foo, созданных после подписки? В вашем нынешнем дизайне их не будет. Если они должны получать уведомления, вы должны изменить stream на Subject<EventArgs> и подписаться на каждую Foo. Субъект будет служить точкой слияния с тем преимуществом, что все подписчики на субъект будут получать сообщения из экземпляров, созданных после подписки наблюдателя.

...