Where to subscribe to internal object events?

I often face a situation where I have to decide where to subscribe to events of an internal object?

For example, my object model looks like this:

class ClassA
{
    public event EventHandler SomeEvent1;
    public event EventHandler SomeEvent2;
    public event EventHandler SomeEvent3;
    public event EventHandler SomeEvent4;
}

class ClassB
{
    private ClassA a;
    public ClassA A 
    {
        get
        {
            return this.a;
        }
    }

    public ClassB()
    {
        this.a = new ClassA();
        // here subscribe to some events (for example, SomeEvent1 and SomeEvent2)
        // this.a.SomeEvent1 += OnSomeEvent1Raised;
        // this.a.SomeEvent2 += OnSomeEvent2Raised;
    }
}

class ClassC
{
    public ClassB B { get; }
}

class ClassD
{
    public ClassC C { get; }

    public void SomeMethod()
    {
        // Here subscribe to another ones events of object C.B.A. For example:
        C.B.A.SomeEvent3 += OnSomeEvent3Raised;
        C.B.A.SomeEvent4 += OnSomeEvent4Raised;
    }

    private void OnSomeEvent4Raised(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }

    private void OnSomeEvent3Raised(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}

      

I tried to create something like a UML diagram: enter image description here

In the structure of the existing code of my project, there are places where such an object model exists (in it there are places where events are signed, implemented as in the above example - CBASomeEvent + =). I don't like it and I want to change it. I want the best practices from you here in this situation.

An alternative approach is to duplicate all class A events in class B, classC, classD. And then replace all event subscriptions to ONE PLACE (I mean, in class B we will subscribe / unsubscribe to all events of the ClassA object. In class C, we will subscribe / unsubscribe to all events of the class B object, and so on. ..) In this case, all subscriptions and unsubscriptions will be in one place. I hope you understand what I mean here.

Again, please rely on your knowledge and experience to tell us how to resolve this situation.

UPDATE

Do you agree with me that event subscriptions and subscriptions should be placed in ONE PLACE? Please answer this additional question as well.

Thanks in advance.

+3


source to share


3 answers


You may be interested in the event aggregator .

This basically separates publishers from subscribers - it's sort of an event container. You can get an event aggregator via dependency injection (like MEF) for each class you want to subscribe or publish.

How I personally use and how it is most is how Rob Eisenberg implemented the event aggregator in Caliburn Micro:



In your case, objects A, B and C will use the same instance of an event aggregator, which means that once events are published to that event aggregator, all of these objects will recognize it. Classes A, B, and C can behave differently, triggered by different handling of certain events.

EDIT

Using an event aggregator is that you subscribe to the aggregator itself with an instance of the class. The communication between the publisher and the subscriber class is based on the same instance of the event aggregator. In the case of Caliburn.Micro, subscribing to certain events occurs by implementing a common interface ( IHandle<>

). For example: if you want to subscribe to MyCustomEvent

, you implement the interface IHandle<MyCustomEvent>

in the class to subscribe. This type of event requires a method implementation void Handle(MyCustomEvent e)

from the interface IHandle<MyCustomEvent>

. This method is called every time a (new) is posted to the shared events aggregator MyCustomEvent

.

+2


source


There is too much stuff in your example public

. Hope I make sense below:

  • ClassB contains an object of type ClassA and handles some ClassA events
  • ClassC contains an object of type ClassB, but events are ignored.
  • ClassD contains an object of type ClassC and handles events from a ClassA object inside a ClassB object in ClassC objects




# 2 and # 3 are not good: ClassC must handle and implement events, handle them, and allow them to "bubble up" (raise their own event) in order to handle ClassD correctly.

Basically, they should all handle all events, reacting to them (as in ClassB for ClassA events) or simply propagating them.

0


source


Find a good solution here:

Csharp-NotificationCenter

0


source







All Articles