icn
icn

Reputation: 2363

How to substitute an event-based class for an observable-based class in C# and System.Reactive?

I have a class which has some events. At present, I decide to shift towards "Observables" since the benefits they propose. To reach this goal, I introduced an Observable property to be replaced with one of the events. Next, I made the event "private" to restrict its accessibility from out of the class. The event is invoked inside the class with a function when it is needed. However, I think It may be a better way to do this job. What is the proper practice? By the way, I am a novice in "System.Reactive," so if I have a misunderstanding with the concept, please clarify the matter. My code is below:

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
            });
    }
}

Upvotes: 0

Views: 252

Answers (2)

HackSlash
HackSlash

Reputation: 5811

Using the advice of @Theodor-Zoulias we make the subject private and only expose the observable through the public property. This provides the expected separation of observable and observer that is expected in reactive pattern. This is why the documentation advises not to use Subject in production. You can do it, if you do it correctly.

public class MyClass
{
    private Subject<SolutionEventArg> _informationSender;

    public MyClass()
    {
        _informationSender = new Subject<SolutionEventArg>();
    }
    
    public IObservable<SolutionEventArg> InformationSenderObservable => _informationSender.AsObservable();

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

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

Upvotes: 1

icn
icn

Reputation: 2363

Thanks to Theodor Zoulias, I finally understood how I could better handle my class. I used ISubject<T> instead of events in my class to send information from my class to another class subscribing to the ISubject<T>.

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<T> implements both IObservable<T> and IObserver<T> simultaneously.

Upvotes: 2

Related Questions