2

我第一次尝试设置 Ninject。我有一个 IRepository 接口和一个 Repository 实现。我正在使用 ASP.NET MVC,我正在尝试像这样注入实现:

public class HomeController : Controller
{
    [Inject] public IRepository<BlogPost> _repo { get; set; }

    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        var b = new BlogPost
                    {
                        Title = "My First Blog Post!",
                        PostedDate = DateTime.Now,
                        Content = "Some text"
                    };

        _repo.Insert(b);

        return View();
    }

    // ... etc
}

这是 Global.asax:

public class MvcApplication : NinjectHttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );

    }

    protected override void OnApplicationStarted()
    {
        RegisterRoutes(RouteTable.Routes);
    }

    protected override IKernel CreateKernel()
    {
        IKernel kernel = new StandardKernel(new BaseModule());
        return (kernel);
    }
}

这是 BaseModule 类:

   public class BaseModule : StandardModule
    {
        public override void Load()
        {
            Bind<IRepository<BlogPost>>().To<Repository<BlogPost>>();
        }
    }

但是,当我浏览到 Index() 操作时,在尝试使用 _repo.Insert(b) 时出现“对象引用未设置为对象的实例”。我遗漏了什么?

4

2 回答 2

3

Ninject 1.0 没有开箱即用的 MVC 支持。有多种使用 MVC 和 Ninject 1.0 的方法散布在网络上。

我建议从 Ninject 主干获取最新代码,其中包括 MVC 支持。然后使用以下内容作为您的应用程序的起点:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using DemoApp.Models;
using Ninject.Core;
using Ninject.Framework.Mvc;

namespace DemoApp
{
    public class MvcApplication : NinjectHttpApplication
    {
        protected override void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );
        }

        protected override IKernel CreateKernel()
        {
            return new StandardKernel(new BaseModule(), new AutoControllerModule(Assembly.GetExecutingAssembly()));
        }
    }
}

与您的原始实现相比,有几件事需要强调......

  • Ninject 有两个 实现名称 NinjectHttpApplication - 一个在 Ninject.Framework.Web 中,一个在 Ninject.Framework.Mvc 中。您似乎正在使用前者,因为后者包含受保护的 RegisterRoutes() 方法。
  • 您需要一种方法给 Ninject 一个钩子到控制器创建中,这是使用 ControllerBuilder 完成的。Ninject.Framework.Mvc.NinjectHttpApplication 注册了 NinjectControllerFactory。如果使用 Ninject 1.0,您必须自己提供。
  • 您需要在容器中注册您的控制器。您可以手动完成,但使用最新的代码提供和 AutoControllerModule 自动为您注册控制器!
于 2009-08-05T04:53:57.733 回答
2

您需要将AutoControllerModule添加到您在创建内核时指定的模块列表中,如下所示:

protected override IKernel CreateKernel()
{
    IKernel kernel = new StandardKernel(
                         new BaseModule(), 
                         new AutoControllerModule(Assembly.GetExecutingAssembly())
                     );
    return (kernel);
}

AutoControllerModule是 Ninject 1.x 中 MVC 支持的一部分。它会扫描您提供给其构造函数的程序集以查找 MVC 控制器类并自动绑定它们。在代码中,您已正确绑定存储库,但 Ninject 不负责激活您的控制器。为了将您的存储库注入到HomeController类的实例中,Ninject 需要负责创建和激活控制器。如果没有AutoControllerModule,MVC 仍然负责创建控制器;因此,Ninject 永远没有机会注入任何成员。一旦 Ninject 负责创建和激活控制器,注入将按预期进行。

AutoControllerModule视为查找所有控制器并生成如下代码(以 HomeController 为例):

Bind<HomeController>.ToSelf();
于 2009-08-05T15:46:22.820 回答