C# 接收未观察到的消息的CatchAll

C# 接收未观察到的消息的CatchAll,c#,.net,linq,system.reactive,C#,.net,Linq,System.reactive,我想知道是否有可能为RxIObservable设置某种全面的功能 它的行为大致如下:“如果没有其他订阅者注意到这条消息,那么就做[某件事]” 现在,我连接了几个互不了解的可观察处理程序,并根据某些属性过滤事件。如果我们收到一条未被处理的消息,我想抛出一个错误,因为这将是一条无效消息。我认为这是一个有趣的问题,所以我去写了一个中等大小的解决方案。我将解决方案分为三个部分:通用实现、示例用法和解释 实施 公共接口已备份 { T值{get;} 布尔{get;} 无效观察(); } 跟踪的公共类:ITr

我想知道是否有可能为Rx
IObservable
设置某种全面的功能

它的行为大致如下:“如果没有其他订阅者注意到这条消息,那么就做[某件事]”


现在,我连接了几个互不了解的可观察处理程序,并根据某些属性过滤事件。如果我们收到一条未被处理的消息,我想抛出一个错误,因为这将是一条无效消息。

我认为这是一个有趣的问题,所以我去写了一个中等大小的解决方案。我将解决方案分为三个部分:通用实现、示例用法和解释

实施
公共接口已备份
{
T值{get;}
布尔{get;}
无效观察();
}
跟踪的公共类:ITracked
{
私有只读T值;
公共跟踪(T值)
{
这个值=值;
}
公共价值
{
获取{返回值;}
}
公共布尔值{get;私有集;}
公众假期
{
这是真的;
}
}
公共接口ITrackableObservable:IObservable
{
IObservable Unobserved{get;}
}
公共类TrackableObservable:ITrackableObservable
{
private readonly ISubject unobserved=新主题();
私有只读IObservable源;
公共可跟踪可观测(IObservable源)
{
this.source=可观察
.Create(observer=>source.Subscribe(
值=>
{
var trackedValue=新跟踪(值);
observer.OnNext(跟踪值);
如果(!trackedValue.IsObserved)
{
未观察到。OnNext(值);
}
},
observer.OnError,
观察员(未完成)
.Publish()
.RefCount();
}
公共不可观测
{
获取{return unobserved.asobserveable();}
}
公共IDisposable订阅(IObserver观察员)
{
返回source.Subscribe(观察者);
}
}
公共静态类TrackableObservableExtensions
{
公共静态ITrackableObservable到TrackableObservable(此IObservable源)
{
返回新的TrackableObservable(源);
}
公共静态IObservable观测(此IObservable源)
{
返回source.Do(x=>x.Observe()).Select(x=>x.Value);
}
公共静态IObservable ObserveWhere(此IObservable源,Func谓词)
{
返回source.Where(x=>predicate(x.Value)).Observe();
}
}
实例 然后我们会看到这个输出:

1:Meow
1:一只名叫拉斯蒂的猫
2:没有名字的马(未观察到)
3:纬
3:一只名叫菲多的狗
4:纬
5:一只名叫西蒙的鸟
解释 这里的想法是确保所有订阅者最终共享对源序列的单个订阅,并且每个值都附带一个
bool
,表示是否观察到该值。每当源序列发出
T
时,我们将其包装为
ITracked
,然后将单个实例传递给所有订阅者。如果观察者愿意,他们可以将该值标记为已观察。一旦所有对观察者的
OnNext
调用返回,如果
ITracked
未标记为已观察,则我们知道它未被观察到


TrackableObservableExtensions
类提供了一些扩展方法,使实现更加流畅,但它们不是实现的一部分。

我认为这是一个有趣的问题,所以我编写了一个中等规模的解决方案。我将解决方案分为三个部分:通用实现、示例用法和解释

实施
公共接口已备份
{
T值{get;}
布尔{get;}
无效观察();
}
跟踪的公共类:ITracked
{
私有只读T值;
公共跟踪(T值)
{
这个值=值;
}
公共价值
{
获取{返回值;}
}
公共布尔值{get;私有集;}
公众假期
{
这是真的;
}
}
公共接口ITrackableObservable:IObservable
{
IObservable Unobserved{get;}
}
公共类TrackableObservable:ITrackableObservable
{
private readonly ISubject unobserved=新主题();
私有只读IObservable源;
公共可跟踪可观测(IObservable源)
{
this.source=可观察
.Create(observer=>source.Subscribe(
值=>
{
var trackedValue=新跟踪(值);
observer.OnNext(跟踪值);
如果(!trackedValue.IsObserved)
{
未观察到。OnNext(值);
}
},
observer.OnError,
观察员(未完成)
.Publish()
.RefCount();
}
公共不可观测
{
获取{return unobserved.asobserveable();}
}
公共IDisposable订阅(IObserver观察员)
{
返回source.Subscribe(观察者);
}
}
公共静态类TrackableObservableExtensions
{
公共静态ITrackableObservable到TrackableObservable(此IObservable源)
{
返回新的TrackableObservable(源);
}
公共静态IObservable观测(此IObservable源)
{
返回source.Do(x=>x.Observe()).Select(x=>x.Value);
}
公共静态IObservable ObserveWhere(此IObservable源,Func谓词)
{
返回source.Where(x=>predicate(x.Value)).Observe();
}
}
实例 然后我们会看到这个输出:

1:Meow
1:一只名叫拉斯蒂的猫
2:没有名字的马(
public class Animal
{
    public int ID { get; set; }
    public string Kind { get; set; }
    public string Name { get; set; }
}

...

IObservable<Animal> animals = ...;
ITrackableObservable<Animal> trackableAnimals = animals.ToTrackableObservable();
trackableAnimals
    .ObserveWhere(a => a.Kind == "Cat")
    .Subscribe(a => Console.WriteLine("{0}: Meow", a.ID));
trackableAnimals
    .ObserveWhere(a => a.Kind == "Dog")
    .Subscribe(a => Console.WriteLine("{0}: Woof", a.ID));
trackableAnimals
    .ObserveWhere(a => a.Name != null)
    .Subscribe(a => Console.WriteLine("{0}: {1} named {2}", a.ID, a.Kind, a.Name));
trackableAnimals
    .Unobserved
    .Subscribe(a => Console.WriteLine("{0}: {1} with no name (unobserved)", a.ID, a.Kind));
new Animal { ID = 1, Kind = "Cat", Name = "Rusty" }
new Animal { ID = 2, Kind = "Horse" }
new Animal { ID = 3, Kind = "Dog", Name = "Fido" }
new Animal { ID = 4, Kind = "Dog" }
new Animal { ID = 5, Kind = "Bird", Name = "Simon" }