Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.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# 在这种情况下实现ObservableBase是最好的还是有其他方法?_C#_.net_System.reactive_Observable - Fatal编程技术网

C# 在这种情况下实现ObservableBase是最好的还是有其他方法?

C# 在这种情况下实现ObservableBase是最好的还是有其他方法?,c#,.net,system.reactive,observable,C#,.net,System.reactive,Observable,首先,我没有找到ObservableBase或AnonymousObservable的定制实现的好例子。我不知道我需要在我的案例中实施哪一个(如果有的话)。情况是这样的 我使用一个第三方库,有一个类我们称之为Producer,它允许我在它上面设置一个委托,比如objProducer.Attach(MyHandler)。MyHandler将接收来自生产者的消息。我试图在生产者周围创建一个包装器,使其可观察,理想情况下使其成为一个独特的类型,而不是仅仅创建一个可观察的实例(比如observable.

首先,我没有找到ObservableBase或AnonymousObservable的定制实现的好例子。我不知道我需要在我的案例中实施哪一个(如果有的话)。情况是这样的

我使用一个第三方库,有一个类我们称之为Producer,它允许我在它上面设置一个委托,比如objProducer.Attach(MyHandler)。MyHandler将接收来自生产者的消息。我试图在生产者周围创建一个包装器,使其可观察,理想情况下使其成为一个独特的类型,而不是仅仅创建一个可观察的实例(比如observable.create)

编辑:第三方制作人具有以下界面

public delegate void ProducerMessageHandler(Message objMessage);
public class Producer : IDisposable {
   public void Start();
   public void Attach(ProducerMessageHandler fnHandler);
   public void Dispose();
}
正如我提到的,我无法控制它的源代码。它的用途如下:创建一个实例,调用Attach并传递一个委托,调用Start,当生产者接收或生成消息时,它基本上会在提供的委托内开始接收消息

我在考虑创建public
类ProducerObservable:observeablebase
,这样当有人订阅它时,我(Rx库)就会将消息推送到观察者那里。似乎我需要在ProducerObservable的构造函数中的某个地方调用Attach,然后我需要以某种方式在附加到它的观察器上调用OnNext。这是否意味着我必须对所有这些进行编码:向类中添加观察者列表
LinkedList
,然后在ProducerObservable上调用SubscribeCore抽象方法时添加观察者?显然,我可以在MyHandler中枚举
LinkedList
,并为每一个调用OnNext。所有这些看起来都可行,但感觉并不完全正确。我希望.net反应式扩展能够更好地应对这种情况,并且至少在基类中的某个地方准备好了
LinkedList
的实现。

在使用Rx的代码中,“生产者”对象通常是通过公共属性或方法公开
IObservable
实例的对象。
Producer
类本身实现
IObservable
的情况不太常见,当它实现时,它通过使用
Rx
在引擎盖下进行重载来实现。您绝对不想自己实现
IObservable

下面是一个可观察对象作为属性公开的示例:

public class Producer
{
    public Producer(ThirdPartyLib.Producer p)
    {
        var c = Observable.Create(observer =>
        {
            ProducerMessageHandler h = msg => observer.OnNext(msg);
            p.Attach(h);
            p.Start();

            return Disposable.Empty;
        }).Publish();

        // Connect the observable the first time someone starts
        // observing
        Stream = Observable.Create(observer =>
        {
            var subscription = c.Subscribe(observer);
            if (Interlocked.Exchange(ref _connected, 1) == 0)
            {
                c.Connect();
            }

            return subscription;
        });
    }

    private int _connected;
    public IObservable<Message> Stream { get; private set; }
}
公共类制作人
{
公共制片人(第三方B.p)
{
var c=可观察的。创建(观察者=>
{
ProducerMessageHandler h=msg=>observer.OnNext(msg);
p、 附(h);
p、 Start();
返回一次性。空;
}).Publish();
//第一次有人启动时连接可观察到的
//观察
流=可观察的。创建(观察者=>
{
var认购=c.认购(观察员);
if(联锁交换(参考连接,1)==0)
{
c、 Connect();
}
退订;
});
}
私人互联网连接;
公共IObservable流{get;private set;}
}
下面是同一个示例,我们通过授权给Rx实际实现了
IObservable

public class Producer : IObservable<Message>
{
    public Producer(ThirdPartyLib.Producer p)
    {
        var c = Observable.Create(observer =>
        {
            ProducerMessageHandler h = msg => observer.OnNext(msg);
            p.Attach(h);
            p.Start();

            return Disposable.Empty;
        }).Publish();

        // Connect the observable the first time someone starts
        // observing
        _stream = Observable.Create(observer =>
        {
            var subscription = c.Subscribe(observer);
            if (Interlocked.Exchange(ref _connected, 1) == 0)
            {
                c.Connect();
            }

            return subscription;
        });
    }

    private IObservable<Message> _stream;

    // implement IObservable<T> by delegating to Rx
    public IDisposable Subscribe(IObserver<Message> observer)
    {
        return _stream.Subscribe(observer);
    }
}
公共类生产者:IObservable
{
公共制片人(第三方B.p)
{
var c=可观察的。创建(观察者=>
{
ProducerMessageHandler h=msg=>observer.OnNext(msg);
p、 附(h);
p、 Start();
返回一次性。空;
}).Publish();
//第一次有人启动时连接可观察到的
//观察
_流=可观察的。创建(观察者=>
{
var认购=c.认购(观察员);
if(联锁交换(参考连接,1)==0)
{
c、 Connect();
}
退订;
});
}
私有IObservable\u流;
//通过委托给Rx实施IObservable
公共IDisposable订阅(IObserver观察员)
{
返回_stream.Subscribe(观察者);
}
}

以下是你应该做的“友好”的事情:

这将在第一个订阅上创建一个
Producer
实例,并保留该
Producer
,直到不再有任何订阅为止。这使它成为“自我管理”和一个更好的解决方案

如果您必须实现自己的类,那么您经常会犯错误。你作为这个问题的答案添加的类有三个,我可以看到

  • 在附加消息处理程序后实例化主题。如果生产者在附加过程中创建消息,则代码将失败
  • 您不跟踪订阅。如果您不跟踪您的订阅,则无法处理它们。Rx查询可以保存开放的昂贵资源,因此您应该尽早处置它们
  • 在处置制作人之前,不要调用
    .OnCompleted()
  • 以下是我对您的类的实现:

    public class ProducerObservable : IObservable<Message>, IDisposable
    {
        private readonly Producer _Producer;
        private readonly Subject<Message> _Subject;
        private readonly CompositeDisposable _Disposables;
    
        public ProducerObservable()
        {
            _Subject = new Subject<Message>();
            ProducerMessageHandler fnHandler = m => _Subject.OnNext(m);
    
            _Producer = new Producer();
            _Producer.Attach(fnHandler);
            _Producer.Start();
    
            _Disposables = new CompositeDisposable();
            _Disposables.Add(_Producer);
            _Disposables.Add(_Subject);
        }
    
        public void Dispose()
        {
            _Subject.OnCompleted();
            _Disposables.Dispose();
        }
    
        public IDisposable Subscribe(IObserver<Message> objObserver)
        {
            var subscription = _Subject.Subscribe(objObserver);
            _Disposables.Add(subscription);
            return subscription;
        }
    }
    
    公共类ProducerObservable:IObservable,IDisposable
    {
    私有只读生产者(u生产者),;
    私人只读主题(u Subject);;
    私人只读可组合可处置设备;
    公共产品可服务()
    {
    _主题=新主题();
    ProducerMessageHandler fnHandler=m=>\u Subject.OnNext(m);
    _生产者=新生产者();
    _生产者。附加(fnHandler);
    _Producer.Start();
    _可处置的=新的可组合的();
    _一次性用品。添加(_生产商);
    _一次性用品。添加(_主题);
    }
    公共空间处置()
    {
    _Subject.OnCompleted();
    _可处置的;可处置的;
    }
    公共IDisposable订阅(IObserver objObserver)
    {
    var订阅=_sub
    
    IObservable<Message> query = ObservableProducer.Create();
    
    IObservable<Message> query = ObservableProducer.Create().Publish().RefCount();
    
    public class ProducerObservable : IObservable<Message>, IDisposable
    {
        private readonly Producer _Producer;
        private readonly Subject<Message> _Subject;
        private readonly CompositeDisposable _Disposables;
    
        public ProducerObservable()
        {
            _Subject = new Subject<Message>();
            ProducerMessageHandler fnHandler = m => _Subject.OnNext(m);
    
            _Producer = new Producer();
            _Producer.Attach(fnHandler);
            _Producer.Start();
    
            _Disposables = new CompositeDisposable();
            _Disposables.Add(_Producer);
            _Disposables.Add(_Subject);
        }
    
        public void Dispose()
        {
            _Subject.OnCompleted();
            _Disposables.Dispose();
        }
    
        public IDisposable Subscribe(IObserver<Message> objObserver)
        {
            var subscription = _Subject.Subscribe(objObserver);
            _Disposables.Add(subscription);
            return subscription;
        }
    }
    
    public class ProducerObservable : IObservable<Message>, IDisposable {
       private readonly Producer _Producer;
       private readonly Subject<Message> _Subject;
    
       public ProducerObservable() {
          _Produder = new Producer();
          _Producer.Attach(Message_Received);
          _Subject = new Subject<Message>();
          _Producer.Start();
       }
    
       public void Dispose() {
          _Producer.Dispose();
          _Subject.Dispose();
       }
    
       public IDisposable Subscribe(IObserver<Message> objObserver) {
          return _Subject.Subscribe(objObserver);
       }
    
       private void Message_Received(Message objMessage) {
          _Subject.OnNext(objMessage);
       }
    }