#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/… Это некрасиво. Я бы посоветовал не делать этого.