【问题标题】:Getting started with Ninject开始使用 Ninject
【发布时间】:2011-02-17 16:28:20
【问题描述】:

我在dimecasts.net 上观看了 Ninject 的前 2 个初学者教程。现在,我想在 ASP.NET MVC 3 中使用 Ninject 2.2。我想要一个带有模拟模型的视图。调用我的服务时,对象引用未设置为对象的实例;

    public class HomeController : Controller
    {
        private readonly IMilestoneService _service;

        public HomeController()
        {
        }

        HomeController(IMilestoneService service)
        {
            _service = service;
        }

        public ActionResult Index()
        {
            ViewBag.Message = "Change Request System";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }

        #region Partial views
        public ActionResult Milestone()
        {
            var result = _service.GetMileStones();//OBJECT REF ERROR
            return View(result);
        }
        #endregion
    }

//####GLOBAL.ASAX
//By using the NinjectHttpApplication, it automatically takes care of controllers, starting up mvc, etc.
//Ninject.Web.Mvc
public class MvcApplication : NinjectHttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    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 = UrlParameter.Optional } // Parameter defaults
        );

    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        //StartNinject();
    }

    #region Inversion of Control

    protected override IKernel CreateKernel()
    {
        return Container;
    }

    static IKernel _container;
    public static IKernel Container
    {
        get
        {
            if (_container == null)
            {
                _container = new StandardKernel(new SiteModule());
            }
            return _container;
        }
    }

    internal class SiteModule : NinjectModule
    {
        public override void Load()
        {
            //Set up ninject bindings here.
            Bind<IMilestoneService>().To<MileStoneService>();
        }
    }
    #endregion
}

我用的是 Razor,他是里程碑局部视图

@foreach (var item in Model)
{
    <div>item.Name</div>
}

最后是主页视图索引

@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>
<p>
   @Html.Action("Milestone");
</p>

编辑 2013 年 11 月 20 日

请注意,Ninject 已经发布了 2.0 版。他们的site 很好地概述了这些变化。注意 StandardModule 现在是 NinjectModule 并且命名空间 Ninject.Core 不再存在。我可以用 Ninject 替换它。

【问题讨论】:

  • 显示您的 ascx 文件的代码或您进行绑定的代码。问题似乎是 ninject 没有将实例绑定到接口。
  • 请展示 mvcapplication 类是如何声明的。
  • 更新了部分视图,没有 ascx 文件我正在使用 razor 引擎。绑定代码已经在 ServiceModule 类下。我不知道您所说的“显示 Mvcapplication 类是如何声明的”是什么意思……也许这就是问题所在。
  • 只读 _service 真的有必要吗?
  • 否,但如果您想设置该属性一次而不让它再次更改,这是合适的。我几乎总是在包含注入依赖项的私有变量上使用只读。

标签: c# asp.net-mvc-3 ninject-2


【解决方案1】:

你的控制器类有问题,依赖的构造函数是private。您的控制器应如下所示:

public class HomeController : Controller
{
    private readonly IMilestoneService _service;

    public HomeController(IMilestoneService service)
    {
        _service = service;
    }

}

甚至不包括公共无参数构造函数,它甚至无效,您的类需要该依赖项才能运行。

事实上,我还在构造函数中插入了一个针对该依赖项的空检查,以确保我的类在构造时有效:

public class HomeController : Controller
{
    private readonly IMilestoneService _service;

    public HomeController(IMilestoneService service)
    {
        _service = service;
        Enforce.NotNull(() => _service); // lambda to auto-magically get variable name for exception
    }

}

您的 MvcApplication 类也可能存在问题。

除了protected void Application_Start(),您还可以覆盖另一个函数protected override void OnApplicationStarted()

这是您调用设置路由的地方:

public class MvcApplication : NinjectHttpApplication
{

    public override void Init()
    {
        base.Init();
        Mappers.Initialize();
    }

    protected override Ninject.IKernel CreateKernel()
    {
        return Ioc.Initialize();
    }

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

    public static void RegisterRoutes(RouteCollection routes) 
    {
        Routing.RegisterRoutes(routes);
        //RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
    }
}

当然,如果你已经打电话给Application_Start 那也没关系,但我在 OP 中没有看到。

【讨论】:

  • 您是否了解将私有构造函数更改为公共的部分?
  • 现在 ninject 正在抛出异常 :( : 使用 HomeController 的隐式自绑定激活 HomeController 时出错 没有构造函数可用于创建实现类型的实例。
  • 所以,等等,我看到你被接受了——那么它有效吗?如果没有,我们会给你分类,然后它就会变成肉汁。
  • 没问题。一旦解决了这些小问题,它应该是一帆风顺的。第一次总是最艰难的。 ;-)
  • 哈哈!我没有看到私有构造函数。
【解决方案2】:

在你的 global.asax 文件中试试这个:

//By using the NinjectHttpApplication, it automatically takes care of controllers, starting up ninject, etc.
//Ninject.Web.Mvc
public class MvcApplication : NinjectHttpApplication
{
    //Your other stuff here. No need to call StartNinject().

    #region Inversion of Control

    protected override IKernel CreateKernel()
    {
        return Container;
    }

    static IKernel _container;
    public static IKernel Container
    {
        get
        {
            if (_container == null)
            {
                _container = new StandardKernel(new SiteModule());
            }
            return _container;
        }
    }

    internal class SiteModule : NinjectModule
    {
        public override void Load()
        {
            //Set up ninject bindings here.
            Bind<IMilestoneService>().To<MileStoneService>();
        }
    }
    #endregion
}

【讨论】:

  • 我无法解析 NinjectHttpApplication。我只有对 Ninject 和 NinjectAdapter 的引用。我看到人们谈论 Ninject.Web,但我的下载(.NET 4.0 版本)中没有包含它。我认为这是因为 2.2 不再需要 Ninject.Web。有什么想法吗?
  • P.Brian:请参阅我的答案中的链接。您可能会发现使用 Ninject.Web.Mvc 中包含的 Ninject 2.1 会更容易。我想我没有关于 Ninject 2.2 以及它是否需要 Ninject.Web.Mvc 的任何信息,除了说 Ninject 已经远离组合主库中的功能并将其推到扩展库中,他们看起来很奇怪会扭转这种情况。
  • @P.Brian.Mackey 单独下载。
  • @Shawn Mclean @qstarin - 现在我收到运行时错误 http 404(找不到资源)。我正在使用上面的类,重新复制了我的 RegisterRoutes 等方法。 (引用了 Ninject.Web.Mvc)。
  • @Shawn Mclean @qstarin - 没关系,重写 MvcApplication 类中的 Init() 并告诉它调用 base.Init() 和 Application_Start() 我回到同一个对象引用错误我们开始了。
【解决方案3】:

我相信如果 Ninject 不能绑定那个接口,你会得到一个绑定错误。这让我觉得 Ninject 没有实例化你的控制器。

你有加入Ninject.Web.Mvc吗?

【讨论】:

  • 对不起,我忘了在我对你其他问题的回答中显示这部分。
  • 哈,不。当然没有。我认为这将是从主站点下载的一部分。猜不到!
猜你喜欢
  • 1970-01-01
  • 2014-12-08
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多