Jan 24, 2016 at 5:56 AM
Edited Jan 24, 2016 at 5:57 AM
Thanks for checking out my project. And thanks for your feedback.
Whilst I do not agree that the design of the usage of IPresenterFactory is flawed, I do agree that the PresenterFactories for Ninject and StructureMap should probably have been written without a requirement that the IView parameter to the Presenter’s constructor
be named "view" .
If you look at the UnityPresenterFactory, there is no such requirement and you can name the IView parameter anything you like.
I disagree that the IPresenterFactory is doing the job of the DI Container. Firstly, we should be referring to an Inversion of Control container (IOC), rather than DI container. The control of resolving the dependency is delegated to the IOC. The factory is
handling the injection of the dependency. If you look at this post by Mark Seemann
, you will see that it is not poor practice to use an IOC inside a factory which has the responsibility of returning to
the framework the instantiated object. If you look at the class "WindsorCompositionRoot" in that article, you will see the example I am referring to (in that case, it is pertinent to the ASP.NET MVC framework).
Going back to the Ninject example, you could probably rewrite the Create method as follows:
public virtual IPresenter Create(Type presenterType, Type viewType, IView viewInstance)
if (presenterType == null)
throw new ArgumentNullException("presenterType");
if (viewType == null)
throw new ArgumentNullException("viewType");
if (viewInstance == null)
throw new ArgumentNullException("viewInstance");
var presenter = Kernel.Get<IPresenter>();
As you can see, there is now no reliance on the IView being named "view". I haven’t thoroughly tested that, but it passes the units tests.
I’ll make a quick comment on some other DI issues.
When you create your bindings for all of your services, you should not do that in the IPresenter factory. That IPresenter factory’s responsibility is solely to instantiate the relevant Presenter for the relevant IView. Your other services, which deliver data
and process business rules, should be bound in a separate place.
So, if we take a simple example, the Program class’s Main method might look something like this:
static void Main()
IKernel kernel = new KernelFactory().CreateKernel();// in here, bind all your services/dependancies etc.
PresenterBinder.Factory = new NinjectPresenterFactory(kernel);
var mainForm = new MainForm();
The last, and probably most important, thing to note is that you will need to manage how and when your IOC disposes of objects. Resolving objects with an IOC is easy. But making decisions on their lifetime can get tricky. Especially in a stateful environment
like Winforms. It is easier with web to scope things to the lifetime of an HttpRequest. But with desktop development, you need to be careful not to create memory leaks.
So, a tool to profile your memory is a good idea, if you can get access to one. I know Redgate's memory profiler has a 30 day trial, so it would be a good idea to make sure your Services and other dependencies are being disposed of when you expect them to.
All the best.