首先,我没有找到ObservableBase或AnonymousObservable的自定义实现的好例子。我不知道在我的情况下我需要实施哪一个。情况就是这样。
我使用的是第三方库,有一个类让我们称它为Producer,它允许我像objProducer.Attach(MyHandler)一样在其上设置委托。 MyHandler将接收来自制作人的消息。我正在尝试在Producer周围创建一个包装器,使其可观察,理想情况下它是一个独特的类型,而不是只创建一个observable实例(如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,它基本上在Producer接收或生成它们时,在提供的委托中启动接收消息。
我正在考虑创建公共class ProducerObservable : ObservableBase<Message>
,以便当有人订阅它时,我会(Rx库会)将消息推送给观察者。看来我需要在我的ProducerObservable的构造函数中调用Attach,然后我需要以某种方式在附加到它的观察者上调用OnNext。这是否意味着我必须对所有这些进行编码:向类中添加观察者列表LinkedList<IObserver<Message>>
,然后在ProducerObservable上调用SubscribeCore抽象方法时添加观察者?然后显然我能够枚举MyHandler中的LinkedList<IObserver<Message>>
并为每一个调用OnNext。所有这些看起来都可行,但感觉并不完全正确。我希望.net反应式扩展可以更好地为这种情况做好准备,至少在基类的某个地方准备好LinkedList<IObserver<Message>>
的实现。
答案 0 :(得分:1)
在使用Rx的代码中,“Producer”对象通常是通过公共属性或方法公开IObservable<T>
实例的对象。 Producer
类本身实现IObservable<T>
的情况并不常见,当它发生时,它通过使用Rx
来完成繁重的工作。你绝对不想自己实现IObservable<T>
。
以下是将observable作为属性公开的示例:
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; }
}
以下是我们通过委托给Rx实际实现IObservable<T>
的相同示例:
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);
}
}
答案 1 :(得分:1)
在这里你应该做些什么才能成为Rx&#34;友好&#34;:
public static class ObservableProducer
{
public static IObservable<Message> Create()
{
return
Observable.Using(() => new Producer(), p =>
Observable.Create<Message>(o =>
{
ProducerMessageHandler handler = m => o.OnNext(m);
p.Attach(handler);
return Disposable.Create(() => o.OnCompleted());
}));
}
}
您可以这样使用:
IObservable<Message> query = ObservableProducer.Create();
您应该允许为所有新订阅创建多个Producer
个实例 - 这就是Rx的工作方式。
但是,如果您只想要一个Producer
实例,请查看在此可观察对象上使用.Publish()
。
以下是如何确保单个Producer
实例是&#34;自我管理&#34;:
IObservable<Message> query = ObservableProducer.Create().Publish().RefCount();
这将在第一个订阅上创建一个Producer
实例,并保留Producer
,直到不再有任何订阅。这使得它能够自我管理&#34;和一个更好的解决方案,滚动你自己的班级。
如果你必须实施自己的课程,那么你经常会犯错误。你作为这个问题的答案添加的课程有三个,我可以看到。
.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;
}
}
我仍然不喜欢它。在撰写本文时,我是[system.reactive]中有三个带银徽章的人中的一个(没有人还有金币),而且我从未实现过我自己的观察。我只是意识到我没有就这个问题打电话给.OnCompleted()
,所以我回去编辑了上面的代码。这是一个雷区。它依靠内置的运营商来做得更好。
ObservableBase
存在的原因是为了防止人们犯错误,但它并没有阻止它。
答案 2 :(得分:0)
这次讨论给了我一个想法。这不是吗?
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);
}
}
因此,在我看来,我们避免额外的水平,额外的观察,只有一个可观察的类型,基本上我只看到优点,没有缺点。