I'm trying to get the IoC concept down with a winforms app. Say I have a presenter whose constructor takes its view and a service as constructor arguments. So in the form code I have something that amounts to this:
mnPresenter = new Presenter(this, new AppService());
where, say AppService is an implementation of IAppService. It's registered in my [autofac]
IoC container. What's the recommended way of getting the "new" out of this presenter construction? Isn't the whole point of using an IoC framework to lose these "new" calls like I'm making above?
I could do something like
mPresenter = new Presenter(this, MyContainer.Resolve<IAppService>())
but that seems to defeat the purpose of IoC. I'm probably missing something fundamental here.
Apologies in advance if I'm missing something obvious.
You need a property in the presenter
and it will be injected by the container, you don't need to pass it as a parameter. What you wrote is a service locator, in fact an anti-pattern for IoC.
If your view is strongly typed and registered with the container too, you can use .SingleInstance lifecycle of Autofac and a property
in your presented, the container will then inject the view instance into your presenter.
You basically look the code in another question: Register a Presenter with a View
Your problem is that there is a dependency cycle between the View and the Presenter, since they depend on each other. The general rule in breaking this dependency cycle is to fallback to property injection, which will work in your case as well.
With MVP, best is to let the View assign itself to a created Presenter by injecting it into a property of the Presenter:
If you can, hide the container from the application. Since you are using MVP, the only things you'll ever need to directly resolve are presenters. So instead of letting the Forms communicate with the Container, let them communicate with a static
PresenterFactory
. This factory will use the container under the covers:Your
PresenterFactory
might look like this:And your Composition Root might look like this:
UPDATE
Perhaps even better would it be to do something like this:
This hides the actual implementation of the presenter from the view and centralizes the registration of the view to the presenter.