Ninject.MVC3、Nuget、WebActivator是什么?

14

我希望设置Ninject来进行简单的测试,同时演示使用Nuget的易用性。我想解析一个示例服务。

public interface ITestService
{
    string GetMessage();
}
public class TestService : ITestService 
{
    public string GetMessage() { return "hello world"; }
}

我运行了NuGet Install-Package NinjectMVC3,它很好地将NinjectMVC3.cs文件放在了我的App_Start文件夹中,并带有一些WebActivator属性来使其加载。

接下来,我在NinjectMVC3.RegisterServices方法中添加了绑定:

private static void RegisterServices(IKernel kernel)
{
   kernel.Bind<ITestService>().To<TestServiceOne>();
}

现在我想要使用 Ninjet 来解决我的 ITestService。
public ActionResult Index()
{
  //[Ninject, give me the service I need]
  ITestService service = ??? 

  ViewBag.Message = service.GetMessage();
  return View();
}

设置Ninject还有其他部分吗?我需要提供解析器吗?

我需要什么代码来解决我的ITestService。

谢谢寻求帮助»

** * * * * * * * * * * * 更新:* * * * * * * * * * * * * * * * **

感谢对“控制器构造函数”注入的伟大回应。只需添加一个带有ITestServcice作为参数的构造函数.... BAMM !!!

private ITestService _service;

public HomeController(ITestService service)
{
  _service = service
}
public ActionResult Index()
{
  ViewBag.Message = _service.GetMessage();
  return View();
}

现在,当我需要直接获取内核时,什么是理想的解决方案?

var kernel = ... // Go grab the kernel from ????? (thanks Judah).
ITestService service = kernel.Get<ITestService>();

我可以看到NinjectMVC3类创建了Kernel,但没有持有或公开对其的引用,也找不到明显的类/方法来“获取内核”。
我假设有一种Ninject的方式可以获取它,但不确定。
** * * * * * * * * * * *(最终)更新:* * * * * * * * * * * * * * * * **
再次感谢答案和评论....
更正:NinjectMVC3类创建了Kernel,并且持有对'Bootstrapper'的引用,该引用上有一个IKernel。
因此,我在App_Start/NinjectMVC3类中添加了一个“解析”方法...非常好用。
public static class NinjectMVC3 /// created by the NinjectMVC3 NuGet  Packagae
{
   // add method to provide a global resolver.   
   public static T Resolve<T>()
   {
       return bootstrapper.Kernel.Get<T>();
   }
}

5
这无疑是一个观点问题,但你的 NinjectMVC3.Resolve<T> 静态方法是服务定位器反模式的一个例子。一般来说,依赖注入应该是一种“告诉,不要询问”的方式。Mark Seemann 在他的博客上讨论了这个问题,可能会有所帮助。http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx - Andy S
2个回答

16
  1. 创建一个新的ASP.NET MVC 3项目
  2. 从Package Console中安装NuGet包:Install-Package Ninject.MVC3
  3. 在HomeController中:

    public class HomeController : Controller
    {
        private readonly ITestService _service;
        public HomeController(ITestService service)
        {
            _service = service;
        }
    
        public ActionResult Index()
        {
            ViewBag.Message = _service.GetMessage();
            return View();
        }
    }
    
    App_Start/NinjectMVC3.cs 中:
  4. private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ITestService>().To<TestService>();
    }       
    

谢谢,看起来很简单。现在保留内核的好方法是什么?使用单例作为全局存储? - Rob

4
将ITestService作为构造函数参数添加到您的控制器中:
private ITestService service;

public MyController(ITestService service)
{
   this.service = service;
}

public ActionResult Index()
{
  ViewBag.Message = this.service.GetMessage();
  return View();
}
Ninject将自动将ITestService注入到您的控制器中。然后在Index方法中使用service字段。
或者,如果您不想让Ninject注入到您的控制器构造函数中,您可以保留创建的内核,然后在Index方法中调用kernel.Get<ITestService>()来获取一个实例:
public ActionResult Index()
{
  var kernel = ... // 去获取我们在应用程序启动时创建的内核。
  ITestService service = kernel.Get<ITestService>();
ViewBag.Message = service.GetMessage(); return View(); }
请参阅Ninject依赖注入MVC3控制器的文档

谢谢,那很有道理。现在保留内核的好方法是什么?使用单例作为全局存储? - Rob
1
我个人有一个叫做Dependency的静态类,其中只有一个方法:Get<T>。它在内部调用核心的Get方法。然后消费代码看起来像这样:Dependency.Get<IFoo>()。 - Judah Gabriel Himango
1
我会考虑在属性上使用[Inject]参数,而不是引用内核或构造函数中的参数方法。如果您的基类上有一个必须传递给每个继承构造函数的接口,则向控制器添加构造函数将导致更冗长的代码。http://ninject.codeplex.com/wikipage?title=Injection%20Patterns - Doug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接