Ninject не стреляет?

Первый раз пытаюсь настроить Ninject. У меня есть интерфейс IRepository и реализация репозитория. Я использую 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). Что я упускаю?


person Matthew Groves    schedule 05.08.2009    source источник
comment
Какую версию Ninject вы используете?   -  person John Clayton    schedule 05.08.2009


Ответы (2)


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, который автоматически регистрирует контроллеры для вас!
person John Clayton    schedule 05.08.2009
comment
Почему мне нужно использовать ControllerBuilder и регистрировать контроллеры? Я не пытаюсь их вводить (пока). - person Matthew Groves; 05.08.2009
comment
Ваше исключение с нулевой ссылкой вызвано тем, что _repo является нулевым, потому что он не вводится в контроллер. Чтобы Ninject мог внедрить ваш репозиторий в контроллер, Ninject должен создать контроллер. Чтобы Ninject смогла создать контроллер, ему необходимо зарегистрировать контроллер, как и о вашем репозитории. Наконец, вам нужно подключиться к MVC, чтобы он использовал Ninject для создания контроллера, что и обрабатывает ControllerBuilder. - person John Clayton; 05.08.2009

Вам необходимо добавить AutoControllerModule в список модулей, который вы указываете при создании ядра, как показано ниже:

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

AutoControllerModule является частью поддержки MVC в Ninject 1.x. Он сканирует сборку, которую вы предоставляете своему конструктору, на предмет классов контроллера MVC и автоматически привязывает их. В коде вы правильно связали свой репозиторий, но Ninject не отвечает за активацию ваших контроллеров. Чтобы ваш репозиторий был внедрен в экземпляр вашего класса HomeController, Ninject должен отвечать за создание и активацию контроллеров. Без AutoControllerModule MVC продолжает создавать контроллеры; следовательно, у Ninject никогда не будет возможности ввести какие-либо члены. Как только Ninject будет отвечать за создание и активацию контроллеров, инъекция произойдет, как и ожидалось.

Думайте о AutoControllerModule как о поиске всех контроллеров и генерации такого кода (HomeController используется в качестве примера):

Bind<HomeController>.ToSelf();
person Peter Meyer    schedule 05.08.2009