Инъекция зависимостей Ninject в MVC3 — вне контроллера

#c# #.net #asp.net-mvc #dependency-injection #ninject

#c# #.net #asp.net-mvc #внедрение зависимостей #ninject

Вопрос:

Мы используем Ninject в нашем проекте MVC3 для внедрения зависимостей. Я использовал NuGet для добавления ссылок на пакеты Ninject и Ninject.MVC3. Когда я это сделал, в моей папке App_Start был создан класс NinjectMVC3:

 public static class NinjectMVC3
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    public static void Start()
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule));
        DynamicModuleUtility.RegisterModule(typeof(HttpApplicationInitializationModule));
        bootstrapper.Initialize(CreateKernel);
    }

    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        RegisterServices(kernel);
        return kernel;
    }

    private static void RegisterServices(IKernel kernel)
    {           
        kernel.Bind<IPrincipal>().ToMethod(c => HttpContext.Current.User);
    }
}
  

До сих пор это отлично работало для устранения зависимостей в моих контроллерах:

 public class HomeController : Controller {
    protected IPrincipal principal { get; set; }

    public HomeController(IPrincipal principal) {
        this.principal = principal;
    }
}
  

Этот контроллер имеет зависимость от IPrincipal, которую я настроил в своем классе bootstrapper для разрешения в HttpContext.Current.User. У меня есть другой класс, который зависит от IPrincipal, который не является контроллером:

 public class NonControllerClass
{
    protected IPrincipal Principal { get; set; }

    public NonControllerClass(IPrincipal principal) {
    }
}
  

Как бы мне решить эту зависимость? Как бы я это сделал, если бы это не было параметром конструктора?
}

Ответ №1:

Что ж, в идеале это никогда не должно быть проблемой. Все зависимости должны быть подключены к вашему контроллеру, и любые зависимости, от которых зависят эти зависимости, также должны автоматически вводиться.

В MVC (почти) все начинается с контроллера. Таким образом, у вас может возникнуть:

 public class HomeController : Controller { 
    protected IMyService myService { get; set; } 

    public HomeController(IMyService myService) { 
        this.myService = myService; 
    } 
} 

public class MyService {
    protected IPrincipal principal;

    public MyService(IPrincipal principal) { this.principal = principal)
}
  

Обратите внимание, что вам не нужно ничего делать, в ваш сервис автоматически внедряются правильные зависимости, потому что ваш сервис был внедрен в ваш контроллер.

Однако могут быть случаи, когда вам потребуется динамически создавать объект. В этом случае вы можете использовать MVC DependencyResolver.

 var principal = DependencyResolver.Current.GetService<IPrincipal>();
  

Однако вам следует избегать этого без крайней необходимости, поскольку это считается антишаблоном (известным как расположение службы). Хотя иногда у вас нет особого выбора.

Если вы не хотите использовать внедрение конструктора, вы можете использовать внедрение свойств.

 public class MyService {
    [Inject]
    public IPrincipal principal {get; set;}
}
  

Комментарии:

1. Что касается DependencyResolver — это ASP.NET Решение, специфичное для MVC. (что нормально) Если, в качестве альтернативы, OP хочет достичь той же функциональности в чистом Ninject, тогда вы можете просто ввести Func<IPrincipal> , чтобы вернуть заводскую функцию, которая создаст новый экземпляр при его вызове.

2. Мне нужно что-то в атрибуте для действия контроллера. Как бы я это внедрил?

3. @Dismissile — Я не верю, что MVC будет использовать внедрение параметров. Вероятно, вам придется сделать что-то вроде создания пользовательского средства вызова действий. Смотрите codeclimber.net.nz/archive/2009/02/10/… Это некрасиво. Я бы посоветовал не делать этого.