Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am pretty comfortable with dependency injection using NInject in MVC3. While working in an MVC3 application, I developed a custom Controller Creation Factory using NInject, so any controller that is created will have dependencies injected in it through this Controller Factory.

Now I am starting to develop a windows application, I want to use Application wide Dependency Injection. i.e. Every object must be created through NInject, so as to ease Unit Testing. Please guide me to ensure that every object created must be though the NInject Factory only.

For example, if on any windows form on Button_Click event I write:

TestClass testClass = new TestClass()

and TestClass has any dependency on, say, ITest then it must be automatically resolved. I know I can use:

Ikernel kernel = new StandardKenel()
//AddBinding()
TestClass testClass = kenel.get<TestClass>();

But I find it tedious to do this every time I want to create an object. It also the forces developer to create the object in a particular way. Can it be made better?

Can I have a central repository for object creation and then every object creation will automatically use that repository?

share|improve this question
1  
Hi Pravin Patil: great question. I made a minor change to your title to make it clearer about what you're asking; feel free to modify if I missed the mark. –  user8 Feb 7 '12 at 12:20
    
@MarkTrapp : Thank for the suitable title. I missed that tagline... –  Pravin Patil Feb 7 '12 at 12:24
    
As minor side note, the project is spelt "Ninject", not "NInject". While it might be that it has been En-Inject, they play on nin-ja theme quite a bit nowadays. :) Cf. ninject.org –  Cornelius Apr 22 at 18:25

5 Answers 5

up vote 7 down vote accepted

For client applications, it's often best to adapt a pattern like MVP (or MVVM) and use data-binding from the form to the underlying ViewModel or Presenter.

For the ViewModels, you can inject the required dependencies using standard Constructor Injection.

In your application's Composition Root you can wire up the entire object graph for your application. You don't need to use a DI Container (such as Ninject) for this, but you can.

share|improve this answer

Windows Forms applications typically have a point of entry that looks like this:

    // Program.cs
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }

If you make this point in code your composition root, you can vastly reduce the number of places where you have code explicitly invoking Ninject as if it were a Service Locator.

    // Program.cs
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var kernel = InitializeNinjectKernel();
        Application.Run(kernel.Get<MainForm>());
    }

From this point, you inject all your dependencies via constructor injection.

public MainForm(TestClass testClass) {
    _testClass = testClass;
}

If your "dependency" is something you need to be able to produce multiple times, then what you really need is a factory:

public MainForm(IFactory<TestClass> testClassFactory) {
    _testClassFactory = testClassFactory;
}

...
var testClass = _testClassFactory.Get();

You can implement the IFactory interface this way to avoid having to create a ton of one-off implementations:

public class InjectionFactory<T> : IFactory<T>, IObjectFactory<T>, IDependencyInjector<T>
{
    private readonly IKernel _kernel;
    private readonly IParameter[] _contextParameters;

    public InjectionFactory(IContext injectionContext)
    {
        _contextParameters = injectionContext.Parameters
            .Where(p => p.ShouldInherit).ToArray();
        _kernel = injectionContext.Kernel;
    }

    public T Get()
    {
        try
        {
            return _kernel.Get<T>(_contextParameters.ToArray());
        }
        catch (Exception e)
        {
            throw new Exception(
                string.Format("An error occurred while attempting to instantiate an object of type <{0}>",
                typeof(T)));
        }
    }

...
Bind(typeof (IFactory<>)).To(typeof (InjectionFactory<>));
Bind(typeof (IContext)).ToMethod(c => c.Request.ParentContext);
share|improve this answer

I always write an Adapter wrapper for any IoC Container, which looks like this:

public static class Ioc
{
    public static IIocContainer Container { get; set; }
}

public interface IIocContainer 
{
    object Get(Type type);
    T Get<T>();
    T Get<T>(string name, string value);
    void Inject(object item);
    T TryGet<T>();
}

For Ninject, specifically, the concrete Adapter class looks like this:

public class NinjectIocContainer : IIocContainer
{
    public readonly IKernel Kernel;
    public NinjectIocContainer(params INinjectModule[] modules) 
    {
        Kernel = new StandardKernel(modules);
        new AutoWirePropertyHeuristic(Kernel);
    }

    private NinjectIocContainer()
    {
        Kernel = new StandardKernel();
        Kernel.Load(AppDomain.CurrentDomain.GetAssemblies());

        new AutoWirePropertyHeuristic(Kernel);
    }

    public object Get(Type type)
    {
        try
        {
            return Kernel.Get(type);
        }
        catch (ActivationException exception)
        {
            throw new TypeNotResolvedException(exception);
        }              
    }

    public T TryGet<T>()
    {
        return Kernel.TryGet<T>();
    }

    public T Get<T>()
    {
        try
        {
            return Kernel.Get<T>();
        }
        catch (ActivationException exception)
        {
            throw new TypeNotResolvedException(exception);
        }           
    }

    public T Get<T>(string name, string value)
    {
        var result = Kernel.TryGet<T>(metadata => metadata.Has(name) &&
                     (string.Equals(metadata.Get<string>(name), value,
                                    StringComparison.InvariantCultureIgnoreCase)));

        if (Equals(result, default(T))) throw new TypeNotResolvedException(null);
            return result;
    }

    public void Inject(object item)
    {
        Kernel.Inject(item);
    }
}

The primary reason for doing this is to abstract out the IoC framework, so I can replace it at any time -- given that the difference between frameworks is generally in configuration rather than in usage.

But, as a bonus, things also become a lot easier for using the IoC framework inside other frameworks that don't inherantly support it. For WinForms, for example, it is two steps:

In your Main method, simply instantiate a container before doing anything else.

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        try
        {
            Ioc.Container = new NinjectIocContainer( /* include modules here */ );
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyStartupForm());
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }
}

And then have a base Form, from which other forms derive, which calls Inject on itself.

public IocForm : Form
{
    public IocForm() : base()
    {
        Ioc.Container.Inject(this);
    }
}

This tells the auto-wiring heuristic to attempt to recursively inject all properties in the form which fit the rules set up in your modules.

share|improve this answer
    
Very nice solution..... I will give it a try. –  Pravin Patil Feb 7 '12 at 14:27
6  
That's a Service Locator, which is a spectacularly bad idea: blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx –  Mark Seemann Feb 7 '12 at 16:21
1  
@MarkSeemann: A service locator is a bad idea, if you access it from everywhere, instead of letting it wire up your top level objects as far down as it can. Read Mark's own comment, a little way down the page: "In such cases you really have no recourse but to move the Composition Root into each object (e.g. Page) and let your DI Container wire up your dependencies from there. This may look like the Service Locator anti-pattern, but it isn't because you still keep container usage at an absolute minimum." (Edit: Wait, you ARE Mark! So what is the difference?) –  pdr Feb 7 '12 at 17:07
1  
The difference is that you can still shield the rest of your code base from the Composer, instead of making a Singleton Service Locator available to any class. –  Mark Seemann Feb 7 '12 at 17:35
2  
@pdr: In my experience, if you're attempting to inject services into things like attribute classes, you're not separating concerns properly. There are cases where the framework you're using makes it practically impossible to use proper dependency injection, and sometimes we're forced to use a service locator, but I'd definitely try to take true DI as far as possible before reverting to this pattern. –  StriplingWarrior Feb 7 '12 at 23:05

Good use of Dependency Injection usually relies on seperating the code which creates objects and the actual business logic. In other words, I would not want my team to frequently use new and create an instance of a class that way. Once it is done, there is no way to easily swap out that created type for another, since you have already specified the concrete type.

So there are two ways to go about fixing this:

  1. Inject the instances that a class will need. In your example, inject a TestClass into your Windows Form so that it already has an instance when it needs it. When Ninject instantiates your form, it automatically creates the dependency.
  2. In cases where you really don't want to create an instance until you need it, you can inject a factory into the business logic. For example, you can inject an IKernel into your Windows Form, and then use that to instantiate TestClass. Depending on your style, there are other ways to accomplish this as well (injecting a factory class, factory delegate, etc).

Doing this makes it easy to swap out both the concrete type of TestClass, as well as modify the actual construction of the test class, without actually modifying the code which uses the test class.

share|improve this answer

I've not used Ninject, but the standard way of creating stuff when you are using a IoC is to do so via a Func<T> where T is the type of object you want to create. So if object T1 needs to create objects of type T2 then the constructor of T1 must have parameter of type Func<T1> which is then stored as a field / property of T2. Now when you want to create objects of type T2 in T1 you invoke the Func.

This totally decouples you from your IoC framework and is the right way to code in an IoC mindset.

The downside to doing this is that it can get annoying when you need to manually wire Funcs or example when your creator requires some parameter, so the IoC cannot autowire the Func for you.

http://code.google.com/p/autofac/wiki/RelationshipTypes

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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