C# 可由事件观察到的完整IO

C# 可由事件观察到的完整IO,c#,system.reactive,C#,System.reactive,有一种方法可以使用observable.FromEvent将事件包装为可观察的。例如,本课程: class Generator<T> { event Action<T> onPush; public IObservable<T> Items => Observable.FromEvent<T>(d => onPush += d, d => onPush -= d); public voi

有一种方法可以使用
observable.FromEvent
将事件包装为可观察的。例如,本课程:

class Generator<T>
{
    event Action<T> onPush;

    public IObservable<T> Items =>
        Observable.FromEvent<T>(d => onPush += d, d => onPush -= d);

    public void Push(T item) => onPush?.Invoke(item);
}
类生成器
{
推送事件动作;
公共IObservable项=>
FromEvent(d=>onPush+=d,d=>onPush-=d);
公共无效推送(T项)=>onPush?.Invoke(项);
}
然而,我还没有找到一种方法来完成一个事件的可观察性——我怎么能做到呢

更新:

为了澄清我的意思,上面的类生成了
IObservable
,它是“无止境的”,永远不会完成。我想通过另一个事件来完成它,而不是让另一个可以观察到。因此,问题可以归结为:


如何使任意
IObservable
提前完成,即要调用的
OnCompleted
通知?

可观察表示通知流或事件。当一个可观测的源来自一个事件时,它们本质上是无限的。可观察对象连接到事件,引用对象,因此支持事件的对象永远不会超出范围。NET/C#没有提供一种方法来表明事件将永远不会被调用,因此直接连接到事件的可观察对象是无止境的

这并不罕见;大多数基于事件的观测从未显式调用过
OnCompleted
,对真实世界进行建模,在现实世界中很难确定什么事情不会再发生

然而,这不是一个问题:可观察到的是指无限运行,并没有造成损害。未订阅的可观察对象不会占用太多资源。如果你对一个可观察的事件不感兴趣,取消订阅所有订阅,你就没事了

一种方法是使用一个
Take
操作符,比如
TakeUntil
操作符(如下所述)。尝试以下代码(使用
生成器
类):

TakeUntil
取消订阅
项目
在出现整数大于3的消息后可观察到。这就是为什么有一个未完成的,没有5,6条消息

此外,正如Enigmativity提到的,您的
生成器
类基本上与
主题
相同,我建议您使用它


原始答案:

从事件中再观察一次,然后使用
.TakeUntil

class Generator<T>
{
    event Action<T> onPush;
    event Action<Unit> onCompleted;

    public IObservable<T> Items =>
        Observable.FromEvent<T>(d => onPush += d, d => onPush -= d)
        .TakeUntil(Completion);

    public IObservable<Unit> Completion =>
        Observable.FromEvent<Unit>(d => onCompleted += d, d => onCompleted -= d);

    public void Push(T item) => onPush?.Invoke(item);
    public void Complete() => onCompleted?.Invoke(Unit.Default);
}
类生成器
{
推送事件动作;
事件行动未完成;
公共IObservable项=>
可观察的.FromEvent(d=>onPush+=d,d=>onPush-=d)
。直至(完成);
公共IObservable完成=>
可观察。FromEvent(d=>onCompleted+=d,d=>onCompleted-=d);
公共无效推送(T项)=>onPush?.Invoke(项);
public void Complete()=>onCompleted?.Invoke(单位默认值);
}

可观察对象表示通知流或事件流。当一个可观测的源来自一个事件时,它们本质上是无限的。可观察对象连接到事件,引用对象,因此支持事件的对象永远不会超出范围。NET/C#没有提供一种方法来表明事件将永远不会被调用,因此直接连接到事件的可观察对象是无止境的

这并不罕见;大多数基于事件的观测从未显式调用过
OnCompleted
,对真实世界进行建模,在现实世界中很难确定什么事情不会再发生

然而,这不是一个问题:可观察到的是指无限运行,并没有造成损害。未订阅的可观察对象不会占用太多资源。如果你对一个可观察的事件不感兴趣,取消订阅所有订阅,你就没事了

一种方法是使用一个
Take
操作符,比如
TakeUntil
操作符(如下所述)。尝试以下代码(使用
生成器
类):

TakeUntil
取消订阅
项目
在出现整数大于3的消息后可观察到。这就是为什么有一个未完成的,没有5,6条消息

此外,正如Enigmativity提到的,您的
生成器
类基本上与
主题
相同,我建议您使用它


原始答案:

从事件中再观察一次,然后使用
.TakeUntil

class Generator<T>
{
    event Action<T> onPush;
    event Action<Unit> onCompleted;

    public IObservable<T> Items =>
        Observable.FromEvent<T>(d => onPush += d, d => onPush -= d)
        .TakeUntil(Completion);

    public IObservable<Unit> Completion =>
        Observable.FromEvent<Unit>(d => onCompleted += d, d => onCompleted -= d);

    public void Push(T item) => onPush?.Invoke(item);
    public void Complete() => onCompleted?.Invoke(Unit.Default);
}
类生成器
{
推送事件动作;
事件行动未完成;
公共IObservable项=>
可观察的.FromEvent(d=>onPush+=d,d=>onPush-=d)
。直至(完成);
公共IObservable完成=>
可观察。FromEvent(d=>onCompleted+=d,d=>onCompleted-=d);
公共无效推送(T项)=>onPush?.Invoke(项);
public void Complete()=>onCompleted?.Invoke(单位默认值);
}

你离重新发明
主题
只有一步之遥。为什么不直接使用它呢?你离重新发明
主题
还有一步之遥。为什么不直接使用它呢?我明白了,但是
IObservable Items
在这里仍然是“无止境的”,而我想通过调用
Complete()
来完成它。我已经更新了问题来澄清它。更新了答案。谢谢你的描述性回答!我最初的意图是发出
OnCompleted
,明确地让订阅者知道,不会有更多的事件,因为事件的所有者已被释放。顺便说一句,
Subject
不这样做。
Subject.OnCompleted
就是这样做的。我明白了,但是
IObservable Items
在这里仍然是“无止境的”,而我想通过调用
Complete()
来完成它。我已经更新了问题来澄清它。更新了答案。谢谢你的描述性回答!我最初的意图是发出
OnCompleted
,明确地让订阅者知道,不会有更多的事件,因为事件的所有者已被释放。顺便说一下,class Generator<T> { event Action<T> onPush; event Action<Unit> onCompleted; public IObservable<T> Items => Observable.FromEvent<T>(d => onPush += d, d => onPush -= d) .TakeUntil(Completion); public IObservable<Unit> Completion => Observable.FromEvent<Unit>(d => onCompleted += d, d => onCompleted -= d); public void Push(T item) => onPush?.Invoke(item); public void Complete() => onCompleted?.Invoke(Unit.Default); }