3

Nearly all of the Ninject examples I've seen explain how to use it with ASP.NET MVC, which will automatically inject dependencies into controllers. How would I use Ninject manually though? Let's say I have a custom ActionResult:

public class JsonResult : ActionResult
{
    [Inject] public ISerializer Serializer { get; set; }

    public JsonResult(object objectToSerialize)
    {
        // do something here
    }

    // more code that uses Serializer
}

Then in my controller, I'm using JsonResult in a method like this:

public ActionResult Get(int id)
{
    var someObject = repo.GetObject(id);
    return new JsonResult(someObject);
}

As you can see, I'm instantiating the object myself, which sidesteps Ninject's injection, and Serializer will be null. However, doing it the following way doesn't seem quite right to me:

public ActionResult Get(int id)
{
    var someObject = repo.GetObject(id);
    return IoC.Kernel.Get<JsonResult>(someObject);
}

Because now there's not only a dependency on Ninject in the controller, but I also have to expose the Ninject kernel in a static class/singleton and ensure that objects that rely on injection are only created via kernel.

Is there a way to somehow configure Ninject to inject the dependency without relying on exposing the kernel? I'd like to be able to use the new keyword if at all possible.

Daniel T.
  • 37,212
  • 36
  • 139
  • 206

2 Answers2

11

Use a factory that gets the kernel injected: E.g.

public class ResultFactory : IResultFactory
{
    public ResultFactory(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public JsonResult CreateJsonResult(object obj)
    {
        var result = this.kernel.Get<JsonResult>();
        result.ObjectToSerialize = obj;
        return result;
    }
}

Inject this factory into the controller and use it to create your action results.

Ryan Hayes
  • 5,290
  • 4
  • 42
  • 52
Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
0

I think you should turn your JsonResult inside out:

public class JsonResult : ActionResult
{
    public ISerializer Serializer { get; private set; }

    public object ObjectToSerialize { get; set; }

    public JsonResult(ISerializer serializer)
    {
        this.Serializer = serializer;
    }

    // more code that uses Serializer
}

This way you can retrieve the JsonResult with the container like this:

public ActionResult Get(int id)
{
    var result = IoC.Kernel.Get<JsonResult>();

    result.ObjectToSerialize = repo.GetObject(id);

    return result;
}

Changing the signature of the JsonResult also enables Ninject to create an instance automatically. Because of this you can let Ninject automatically inject it as dependency into your controller:

public MyController(JsonResult result)
{
    this.result = result;
}

public ActionResult Get(int id)
{
    this.result.ObjectToSerialize = repo.GetObject(id);

    return this.result;
}
Steven
  • 166,672
  • 24
  • 332
  • 435
  • This doesn't seem any different than what I had. It just reverses the `IoC.Kernel.Get<>` with the `ObjectToSerialize`. I'd like to optimally be able to remove the `IoC.Kernel.Get<>` call completely. – Daniel T. Nov 03 '10 at 07:48
  • When you want to remove the `IoC.Kernel.Get<>` calls, you should let Ninject inject your dependencies in the controller's constructor. By changing the `JsonResult` the way I showed, allows you to do automatic constructor injection. Look at my updated example. – Steven Nov 03 '10 at 08:04