I am thinking of applying a real dependency injection library to my toy C#/GTK# desktop application. I chose NInject, but I think this is irrelevant to my question.

There is a database object, a main window and several utility window classes. It's clear that I can inject the database into every window object, so here DI is useful. But does it make sense to inject utility window classes into other window classes?

Example: I have classes such as:

class MainWindow {…}
class AddItemWindow {…}
class AddAttachmentWindow {…}
class BrowseItemsWindow {…}
class QueryBuilderWindow {…}
class QueryBrowserWindow {…}
class PreferencesWindow {…}

Each of the utility classes can be opened from MainWindow. Some utility windows can also be opened from other utility windows. Generally, there might be a really complex graph of who can open whom. So each of those classes might need quite a lot of other window classes injected. I'm worried that such usage will go against the suggestion not to inject too many classes at once and become a code smell. Should I use some kind of a service locator object here?


I'd suggest a UtilityWindowOpener class. Its methods will open the various utility windows. Then you can just inject a UtilityWindowOpener anywhere you may need to open a utility window. The UtilityWindowOpener will then have the various utility windows injected (or possibly create them on demand, that's hidden behind the interface). It'll also bring all navigation logic into fewer locations.

  • So, a kind of service locator which would get its dependencies from DI framework?
    – liori
    Dec 15 '12 at 20:46
  • @liori, I'd distinguish it from the service locator because it wouldn't return the utility windows. It would open the utility windows based on the methods called. Dec 15 '12 at 20:46

To avoid overinjection instead of injecting all Window's objects of classes *Window into MainWindow you could use Ninject.Extension.Factory. In this case Abstract Factory could has following interface:

public interface IWindowFactory
    AddItemWindow CreateAddItemWindow();
    AddAttachmentWindow CreateAddAttachmentWindow();
    /* etc */

And then add binding to Load implementation of Ninject.NinjectModule:

    .NamedLikeFactoryMethod<AddItemWindow, IWindowFactory>(f => f.CreateIWindowFactory());

    .NamedLikeFactoryMethod<AddItemWindow, IWindowFactory>(f => f.CreateIWindowFactory());

/* etc */

// and factory binding

Two additional points:

  • There is an excelent article by Mark Seemann Pattern Recognition: Abstract Factory or Service Locator? — so this solution is ok, if you care about Serice Locator anti-pattern, and …
  • To make it 100% not the Serice Locator anti-pattern make sure that Abstract Factory creates only Windows objects, not everything.
  • According to the mentioned article Pattern Recognition: Abstract Factory or Service Locator you have just created a Service Locator.
    – xmedeko
    Jun 16 '15 at 14:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.