Инъекция Ninject PerRequest - PullRequest
       20

Инъекция Ninject PerRequest

2 голосов
/ 24 апреля 2011

У меня есть приложение MVC 2.0, использующее Ninject.Web.Mvc2 и шаблон репозитория (построенный на основе структуры сущностей). Я пытаюсь создать новый 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]);
    }

Класс Wrapper - это просто общий объект для включения всего, что я хочу уничтожить в конце запроса. В этом конкретном случае я использую его для создания моего нового 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 в первый раз, он прекрасно работает. Если я нажму «обновить» (или я предполагаю, что постбэк тоже), _db - это Null. Когда я пытаюсь пройтись по отладчику, я обнаруживаю, что метод Controller Index () вызывается до вызова Application_BeginRequest (). Я думал, что у меня есть понимание «конвейера» (я привык называть вещи жизненным циклом страницы из WebForms), но теперь я немного растерялся. Может кто-нибудь уточнить, где в моем мозгу пересечены провода? Как я уже сказал, это, вероятно, не самый красивый метод, но у меня было всего около полутора недель, чтобы изучить MVC, DI с Ninject, Repository и Entity Framework, поэтому, пожалуйста, не думайте, что вы говорите плохо мне, если кажется, что я сломал что-то очень простое.

1 Ответ

1 голос
/ 26 апреля 2011

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

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

...