Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 合并从多个实例触发的事件的可观察序列的正确方法_C#_.net_Events_System.reactive_Observer Pattern - Fatal编程技术网

C# 合并从多个实例触发的事件的可观察序列的正确方法

C# 合并从多个实例触发的事件的可观察序列的正确方法,c#,.net,events,system.reactive,observer-pattern,C#,.net,Events,System.reactive,Observer Pattern,假设我有一个工厂方法,它可以大量生成T类型的实例,我需要一个Rx可观察序列,用于从工厂方法中生成的所有实例触发的事件 像我在下面所做的那样使用Merge()是否是实现这一目标的正确和最佳方法 我做这件事的另一种方法是使用静态事件并从中生成可观察序列,但是我通常不喜欢使用静态事件,我很好奇任何Rx专家认为在这种情况下什么是最佳的 public T MakeFoo<T>() where T: Foo, new() { this.instanceOfObservable.Merge

假设我有一个工厂方法,它可以大量生成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);
    }
}
public T MakeFoo(),其中T:Foo,new()
{
this.instanceOfObservable.Merge(新的T());
回归自我;
}
公共类ObserveSequence:IObservable,IDisposable
{
私有可观测流;
公共可观测序列()
{
}
//对于T的每个新实例,在工厂方法中调用此方法
公共无效合并(Foo实例)
{
if(this.stream==null)
{
this.stream=Init(实例);
}
其他的
{
IObservable next=Init(实例);
this.stream.Merge(下一步);
}
}
私有IObservable Init(Foo实例)
{
返回可观察的.FromEvent
(处理程序=>
{
EventHandler eh=(发送方,e)=>{
处理程序(e);
};
返回eh;
},
eh=>instance.SomeEvent+=eh,
eh=>instance.SomeEvent-=eh)
.重复
.重试()
.Publish()
.RefCount();
}
公共空间处置()
{
}
公共IDisposable订阅(IObserver观察员)
{
返回流。订阅(观察者);
}
}

这不太可能按您想要的方式工作,并且可能会导致堆栈中断性能问题。对于添加的每个实例,都会在第一个实例和最终观察者之间向堆栈添加另一个调用。如果实例太多,可能会导致堆栈崩溃


更重要的是潜在的错误功能。观察者是否希望从订阅后创建的所有
Foo
s收到通知?在您当前的设计中,它们不会。如果他们应该收到通知,您应该将
更改为
主题
,并让它订阅每个
Foo
。主题将作为一个合并点,其好处是该主题的所有订阅者都将从观察者订阅后创建的实例中获取消息。

像这样滥用
合并
不是很有效。最直接的方法是通过一个主题,这是一个你可以手动控制的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;
    }
}
公共静态类MyAwesomeFoodFactory
{
只读静态主题someEvents=新主题();
公共静态IObservable NotificationsFromAllTheEvents{get{return someEvent;}}
公共静态Foo MakeANewFoo()
{
var ret=new Foo();
订阅(someEvents);//注意:我们从不取消订阅,*evar*
返回ret;
}
}

看起来不错,但我找不到事件的.Subscribe()扩展方法,它在什么命名空间和/或程序集中?我正在使用System.Reactive v.1.0.10621.0和runtime v.4.0.30319如果您无法订阅事件,我假设Foo上有一个名为SomeEvent的属性,该属性返回IObservable。您可以编写一个SomeEvent属性,该属性只返回Observable.FromEvent,如果这是您实际包装的内容的话