Как я могу использовать Ninject с ActionResults, делая контроллер независимым от IoC-framework?

Почти все примеры Ninject, которые я видел, объясняют, как использовать его с ASP.NET MVC, который автоматически вводит зависимости в контроллеры. Как бы я использовал Ninject вручную, хотя? Допустим, у меня есть собственный ActionResult:

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

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

    // more code that uses Serializer
}

Затем в моем контроллере я использую JsonResult в таком методе:

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

Как видите, я сам создаю экземпляр объекта, который обходит инъекцию Ninject, и Serializer будет нулевым Тем не менее, делать это следующим образом не совсем правильно для меня:

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

Потому что теперь в контроллере есть не только зависимость от Ninject, но я также должен представить ядро ​​Ninject в статическом классе / синглтоне и убедиться, что объекты, основанные на внедрении, создаются только через ядро.

Есть ли способ как-то настроить Ninject для внедрения зависимости, не полагаясь на раскрытие ядра? Я хотел бы иметь возможность использовать new ключевое слово, если это вообще возможно.

2 ответа

Решение

Используйте фабрику, которая вводит ядро: Например,

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;
    }
}

Вставьте эту фабрику в контроллер и используйте ее для создания результатов ваших действий.

Я думаю, что вы должны повернуть JsonResult наизнанку:

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
}

Таким образом, вы можете получить JsonResult с таким контейнером:

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

    result.ObjectToSerialize = repo.GetObject(id);

    return result;
}

Изменение подписи JsonResult также позволяет Ninject автоматически создавать экземпляр. Из-за этого вы можете позволить Ninject автоматически внедрить его как зависимость в ваш контроллер:

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

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

    return this.result;
}
Другие вопросы по тегам