C# 如何仅在第一个订阅上强制对象构造?

C# 如何仅在第一个订阅上强制对象构造?,c#,reactive-programming,C#,Reactive Programming,在使用Rx的第一步中,我被困在这里: public class DisposableResourceDemo : IDisposable { public DisposableResourceDemo() { Console.WriteLine("DisposableResourceDemo constructor."); } public void Dispose() { Console.WriteLine("DisposableRes

在使用Rx的第一步中,我被困在这里:

public class DisposableResourceDemo : IDisposable
{
    public DisposableResourceDemo() {
        Console.WriteLine("DisposableResourceDemo constructor.");
    }

    public void Dispose() {
        Console.WriteLine("DisposableResourceDemo.Dispose()");
    }

    public void SideEffect() {
        Console.WriteLine("DisposableResourceDemo.SideEffect()");
    }
}

[Test]
public void ShowBehaviourOfRxUsing()
{
    var test = Observable.Using(() =>
        {
             // This should happen exactly once, independent of number of subscriptions,
             // object should be disposed on last subscription disposal or OnCompleted call 
                return new DisposableResourceDemo();
        },
        (dr) =>
        {
            return Observable.Create<string>(
                (IObserver<string> observer) =>
                {
                    dr.SideEffect();
                    var dummySource = Observable.Return<string>("Some Text");

                    return dummySource.Subscribe(observer);
                });
        }).Publish().RefCount();


    Console.WriteLine("before 1st subscription.");
    test.Subscribe(Console.WriteLine, () => Console.WriteLine("OnCompleted in 1st."));
    Console.WriteLine("before 2nd subscription.");
    test.Subscribe(Console.WriteLine, () => Console.WriteLine("OnCompleted in 2nd."));
}

请注意,在两个订阅之后手动调用Connect(),这并不是我想要的,尽管输出与预期的一样

我不完全确定你在这里想要实现什么。您似乎想要共享可观察序列及其相关资源。因此,实现这一点的标准方法是使用从.Replay()和.Publish()等获取的可连接可观察类型

您说您不想使用.Connect(),而是使用非常常见的.RefCount()。但是,您的序列已完成。您还使用了扩展方法Subscribe(…),它将在内部创建一个自动分离观察者,即当序列完成时,它将断开连接

所以我的问题是,内部序列真的应该完成吗? 如果答案是肯定的,那么为什么第二次订阅会收到OnComplete通知…它已经发生了,它是在过去。也许你真的想重播OnComplete,在这种情况下,也许。重播(1)是你想要的。
如果答案是否定的,那么您可以通过在.Publish()之前或在Observable.Return之后放置Concat(Observable.Never())来轻松解决这个问题。

您是否考虑过使用
Lazy
?是的,但是Lazy没有实现IDisposable,所以我一直使用Observable.using。我也有这样的印象,解决方案在Rx内部。我猜答案是——谁在“完成”事件中崛起?以及为什么“2中未完成”出现在创建的outher Observer(
DisposableResourceDemo
)之前。正如我从代码内部观察者
dummySource
订阅外部观察者
DisposableResourceDemo
中看到的那样,我预计热观察者如果已经完成了新的订阅,就会收到OnComplete(),甚至可能是发生的OnError。至少这是我在这里想要的行为:第一次订阅获取所有消息,第二次订阅获取订阅时剩余的消息。我的观点清楚了吗?顺便说一句:@Lee:你的书很棒!我看不出Replay在这里有什么帮助,您能解释一下吗?
}).Concat(Observable.Never()).Publish().RefCount()是解决方案!谢谢你的提示。
before 1st subscription.
DisposableResourceDemo constructor.
DisposableResourceDemo.SideEffect()
Some Text
OnCompleted in 1st.
DisposableResourceDemo.Dispose()
before 2nd subscription.
--> [happy with missing "Some Text" here]
OnCompleted in 2nd.
--> [unhappy with second instantiation here] 
DisposableResourceDemo constructor.
DisposableResourceDemo.SideEffect()
DisposableResourceDemo.Dispose()