【问题标题】:How to substitute an event-based class for an observable-based class in C# and System.Reactive?如何在 C# 和 System.Reactive 中将基于事件的类替换为基于可观察的类?
【发布时间】:2020-11-08 12:11:21
【问题描述】:

我有一堂课,里面有一些活动。目前,我决定转向“Observables”,因为它们提出了好处。为了达到这个目标,我引入了一个 Observable 属性来替换其中一个事件。接下来,我将事件设为“私有”,以限制其在课堂外的可访问性。该事件在需要时使用函数在类内部调用。但是,我认为这可能是完成这项工作的更好方法。什么是正确的做法?顺便说一句,我是“System.Reactive”的新手,所以如果我对这个概念有误解,请澄清此事。我的代码如下:

public class MyClass
{
    public MyClass()
    {
        InformationSenderObservable=Observable.FromEventPattern<SolutionEventArg>(ev =>InformationSender += ev, ev => InformationSender -= ev);
    }
    private event EventHandler<SolutionEventArg> InformationSender;
    public IObservable<EventPattern<SolutionEventArg>> InformationSenderObservable { get; }

    internal void DoSomething()
    {
        // long calculation
        SendInformation();
    }

    private void SendInformation()
    {
        InformationSender?.Invoke(this,new SolutionEventArg()
            {
                InfoProxyData = GetDetailsForBestCompressedData(),
                ParallelProcess = parallelProcessing
            });
    }
}

【问题讨论】:

  • 你之所以使用InformationSender事件是因为你不知道还有什么其他的方式可以向observable发送信息吗?在这种情况下,您可以考虑使用Subject&lt;T&gt;,它既是可观察的又是观察者。
  • Theodor Zoulias 是的,我之前使用事件将信息从这个类发送到其他类。但是,我不知道用 observables 替换事件的最佳实践是什么。我避免使用Subject&lt;T&gt;,因为我读过它违反了类的单一责任模式。请为我澄清这件事。
  • 根据我的经验,这些科目在实践中表现得很好。您想要的是一个可以向所有订阅者传播独特通知的热可观察对象,并且开箱即用的主题可以高效且具有线程安全性地做到这一点。免责声明:我不是 RX 理论家。 :-)
  • 更正:主题未同步开箱即用。如果您同时从多个线程生成通知,则必须向消费者提供同步主题:public IObservable&lt;SomeType&gt; TheStreamOfEvents =&gt; _subject.Synchronize();

标签: c# events design-patterns observable system.reactive


【解决方案1】:

多亏了 Theodor Zoulias,我终于明白了如何才能更好地处理我的课程。我使用ISubject&lt;T&gt; 而不是我班级中的事件将信息从我的班级发送到另一个订阅ISubject&lt;T&gt;的班级。

public class MyClass
    {
        public MyClass()
        {
            InformationSenderObservable=new Subject<SolutionEventArg>();
        }
        
        public ISubject<SolutionEventArg> InformationSenderObservable { get; }

        internal void DoSomething()
        {
            // long calculation
            SendInformation();
        }

        private void SendInformation()
        {
            try
            {
                InformationSenderObservable.OnNext(new SolutionEventArg()
                {
                    InfoProxyData = GetDetailsForBestCompressedData(),
                    ParallelProcess = parallelProcessing
                });
            }
            catch (Exception e)
            {
                InformationSenderObservable.OnError(e);
            }
        }
    }

ISubject&lt;T&gt; 同时实现IObservable&lt;T&gt;IObserver&lt;T&gt;

【讨论】:

  • 您可能希望公开IObservable&lt;SolutionEventArg&gt; 而不是ISubject&lt;SolutionEventArg&gt;,否则淘气的消费者可能会开始代表MyClass 向其他订阅者发送通知。 :-) 在低信任环境中,您可以考虑使用AsObservable 运算符完全隐藏底层主体的身份(以防止消费者将IObservable 转换为ISubject)。
猜你喜欢
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
相关资源
最近更新 更多