How do I use Ninject with ActionResults while maki

2019-03-31 10:11发布

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.

2条回答
2楼-- · 2019-03-31 10:35

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;
}
查看更多
来,给爷笑一个
3楼-- · 2019-03-31 10:51

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.

查看更多
登录 后发表回答