C# 合并IObservable<;布尔>;和可观察的<;例外情况>;当出现异常时,一个可观察到的错误

C# 合并IObservable<;布尔>;和可观察的<;例外情况>;当出现异常时,一个可观察到的错误,c#,system.reactive,reactive-programming,observable,C#,System.reactive,Reactive Programming,Observable,我试图创建一个单独的可观察对象,其中OnNext流来自一个可观察对象,onnerror流来自另一个可观察对象 我这样做的原因是因为我试图包装一个我无法控制的类,并使用事件来传递其状态。它有两个事件,一个表示其已完成(bool),另一个表示发生异常 IObservable<Exception> error = Observable.FromEventPattern<ExceptionRoutedEventArgs>(foo, "Failed")

我试图创建一个单独的可观察对象,其中OnNext流来自一个可观察对象,onnerror流来自另一个可观察对象

我这样做的原因是因为我试图包装一个我无法控制的类,并使用事件来传递其状态。它有两个事件,一个表示其已完成(bool),另一个表示发生异常

IObservable<Exception> error = Observable.FromEventPattern<ExceptionRoutedEventArgs>(foo, "Failed")
               .Select(x => x.EventArgs.ErrorException);

IObservable<bool> opened = Observable.FromEventPattern<RoutedEventArgs>(foo, "Opened")
               .Select(x => ((Bar)x.Sender).IsOpen);
现在有很多原因说明上面的代码与任何可能存在的代码都不相似,但我希望其意图是明确的


我认为实现这一点的方法是使用主题,但我听说应该避免使用主题,因为它在函数概念中引入了状态。我的想法是,在下一个和一个错误流中将两个观察值合并为一个观察值似乎应该存在:)

您可以使用
观察值。创建

var combined = Observable.Create<bool>(o =>
{
    var openSub = opened.Subscribe(o);
    var errorSub = error.Subscribe(o.OnError);
    return new CompositeDisposable(openSub, errorSub);
});
虽然仅仅因为您的源代码使用异常作为控制流并不意味着您必须这样做-为什么不直接将
异常
投影到
,然后在成功时得到
,在失败时得到

var combined = opened.Merge(error.Select(_ => false));
试试这个:

var combined =
    opened
        .Materialize()
        .Merge(error.Select(e => Notification.CreateOnError<bool>(e)))
        .Dematerialize()
        .Synchronize();
var组合=
开的
.具体化
.Merge(error.Select(e=>Notification.CreateOnError(e)))
.非物质化()
.Synchronize();

在我看来好像
错误
打开
的类型是错误的,如果不是
IObservable错误
IObservable打开
?@Lukazoid oops,修复了这个问题谢谢,这两个解决方案看起来都很棒!我之所以包括这些异常,是因为我想在以后记录它们。所以我不能使用你的第三个建议。记住,如果你的序列出错,那么它也会终止。i、 e.如果您在错误序列上获得一个值(异常),并在输出序列中作为
OnError
生成该值,则该值将是该序列中的最后一个值。因此,如果您想继续监听更多的值,这可能不是您想要的,或者您可以在其上打一个
.Repeat()
var combined = opened.Merge(error.Select(_ => false));
var combined =
    opened
        .Materialize()
        .Merge(error.Select(e => Notification.CreateOnError<bool>(e)))
        .Dematerialize()
        .Synchronize();