Инъекция Ninject PerRequest

#asp.net-mvc-2 #pipeline #ninject-2

#asp.net-mvc-2 #конвейер #ninject-2

Вопрос:

У меня есть приложение MVC 2.0, использующее Ninject.Web.Mvc2 и шаблон репозитория (построенный на модели entity framework). Я пытаюсь создать новый ObjectContext, который будет работать только в течение срока действия запроса. Я пытаюсь выполнить это следующим образом:

 protected override IKernel CreateKernel(){
    var kernel = new StandardKernel();
    kernel.Load(Assembly.GetExecutingAssembly());
    return kernel;
}

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

Затем у меня закончились идеи для сохранения этого достаточно общего, поэтому я приступил к работе в BeginRequest:

     protected void Application_BeginRequest()
    {
         string EntityConnectionString = ConfigurationManager.ConnectionStrings["Entities"].ConnectionString;
         HttpContext.Current.Items.Add(_PerRequestContextObjectKey, new EntityFrameworkContextWrapper(EntityConnectionString));
         this.Kernel.Bind<IUserRepository>().To<UserRepository>().WithConstructorArgument("ContextWrapper", HttpContext.Current.Items[_PerRequestContextObjectKey]);
    }
  

Класс-оболочка — это просто универсальный объект для включения всего, что я хочу уничтожить в конце запроса. В данном конкретном случае я использую его для создания моего нового ObjectContext, а также для реализации IDisposable, чтобы я мог сделать следующее:

     protected void Application_EndRequest()
    {
        foreach (var Item in HttpContext.Current.Items)
        {
            if (Item.GetType() == typeof(IPerRequestLifetimeObjectWrapper))
            {
                (Item as IPerRequestLifetimeObjectWrapper).Dispose();
            }
        }
    }
  

Я уверен, что это не самый красивый способ сделать это, но на данный момент я пытаюсь двигаться дальше, поскольку я потратил так много времени на «изучение» всего этого материала.

Затем мой контроллер вводится следующим образом:

 public class AdminUserController : Controller
{
    // Mark for Ninject
    [Inject]  public IUserRepository _userRepo { get; set; }

    public ViewResult Index( )
    {
        return View(_userRepo.Get);
    }

    public ViewResult Edit(Guid UserUID)
    {
        return View(_userRepo.GetById(UserUID));
    }
}
  

и мой репозиторий также будет введен:

     [Inject]
    public UserRepository(EntityFrameworkContextWrapper ContextWrapper )  
        // Mark for Ninject Dependency Injection 
        // Must receive Wrapper that contains active ObjectContext
    {
        _db = ContextWrapper.Entities;  //Not actually named this, just easier for typing right now
    }
  

Когда мой контроллер вызывает метод Get внутри моего объекта UserRepository в первый раз, он отлично работает. Если я нажму refresh (или, я предполагаю, также postback), _db равно нулю. Когда я пытаюсь выполнить пошаговое выполнение в отладчике, я обнаруживаю, что метод Controller Index( ) вызывается перед вызовом Application_BeginRequest(). Я думал, что у меня есть понимание «конвейера» (я привык называть вещи жизненным циклом страницы из WebForms), но теперь я немного заблудился. Может кто-нибудь уточнить, где в моем мозгу пересеклись некоторые провода? Как я уже сказал, это, вероятно, не самый красивый метод, но у меня было всего около полутора недель, чтобы изучить MVC, DI с Ninject, репозиторий и Entity Framework, поэтому, пожалуйста, не думайте, что вы говорите со мной свысока, если кажется, что я нарушил что-то очень простое.

Комментарии:

1. вы не должны Bind вводить BeginRequest. Посмотрите на образец и используйте модуль для их размещения или, как минимум, делайте это один раз для каждого HttpApplication

Ответ №1:

Почему бы вам просто не использовать InRequestScope? Что вы делаете, так это добавляете новую привязку для каждого запроса. Это приведет к серьезным проблемам. Смотрите https://github.com/ninject/ninject.web.mvc/wiki/Unit-of-work-pattern-with-nhibernate

Это NHilbernate, но вы можете сделать то же самое с EntityFramework

Комментарии:

1. Я все еще новичок во всем этом, поэтому я не знал об InRequestScope. Я обязательно посмотрю на это. Из того, что я вижу онлайн, на первый взгляд кажется, что это именно то, что мне нужно. Спасибо!