2

When implementing DI, both Mark Seemann, and Misko Hevery say that constructors should be simple, and should only receive dependencies. They should not do anything else. (here and here)

However, often I would like to subscribe to events of the passed in dependencies, but if I do this in the constructor, then the constructor does more than receiving its dependencies, and if I don't, then the object is not fully initialized.

Would it be correct, then, to instantiate those objects which need to subscribe to events in the composition root, hook up their events, and then inject those instantiated objects?

For example:

// Composition root
Panel panel = new Panel();
Button button = new Button();
panel.OnButtonClick += button.Click;

Register<Panel>().AsSingle(panel);
Register<Button>().AsSingle(button);

// Panel Class
private Button _button;

public Panel(Button button)
{
    _button = button;
}

void OnButtonClick()
{
    // handle button click
}

as opposed to:

//composition root
Register<Panel>().AsSingle(panel);
Register<Button>().AsSingle(button);

// Panel Class
private Button _button;

public Panel(Button button)
{
    _button = button;
    OnButtonClick += button.Click
}

void OnButtonClick()
{
    // handle button click
}
jmrah
  • 3,633
  • 2
  • 20
  • 30
  • 1
    I just realized that in order for the events to be hooked up in the composition root, the OnButtonClick method would need to be public, which is not desirable. It also hides the fact that Panel is subscribing to Button's events, which is also not ideal for the person trying to read and understanding the class. – jmrah Aug 22 '13 at 14:35

2 Answers2

1

Yes, wiring up the events in the composition root would be the correct approach here.

Darin Dimitrov
  • 960,118
  • 257
  • 3,196
  • 2,876
0

This answer is primarily opinion based.

I usually does not use DI to presentation layer, because I assume the best use of DI is to make a persistence ignorance classes in domain (business) layer. The use of DI though, is to aim for stateless service class. It process requests regardless any specified state and is event-less, thus eliminate the need of events inside the service class.

What you want to create maybe is a control class, and not service class, therefore, assigning event is a real problem here. However, I don't think wiring an event violates the constructor rules thing, because it is just assinging event.

  1. Why is it eventless?

    It accept request, and process it. If you need something to do like: afterProcess, beforeProcess, etc, you can define the specific event in classes, and passing the interfaces as dependency.

  2. What if I need to do event based?

    Sometimes you need an event to be passed in some cases. You can do parameter injection using Func (or adapter in java) instead hooking it in the constructor.

Fendy
  • 4,155
  • 1
  • 17
  • 24