Can I specify the scope in Ninject for only this s

2020-04-07 06:37发布

问题:

Earlier I asked this question. The answer to which resulted into another question like thou seeth before thee.

The initial problem

My problem is, that I have a custom MembershipProvider using an AccountRepository using an ObjectContext. Because the MembershipProvider is a Singleton in MVC (as I understand), the AccountRepository and its ObjectContext should be injected once and stay there for the remainder of the MembershipProvider's life time.

However, in my controllers I also use repositories with object contexts. In these controllers I need the object context to be shared between the repositories with a request. I have the following binding:

Bind<IMyContext>().To<MyObjectContext>().InRequestScope();
// put bindings here
Bind<IAccountRepository>().To<EFAccountRepository>

and in the Application_Start()

kernel.Inject(Membership.Provider);

The problem is that Ninject apparently calls dispose on the object context when it thinks the request is done (I think after 30 seconds).

My (not-working) solution

I noticed that when you set your bindings you can specify "when injecting into". The problem is, that I need "when injecting into when injecting into". I.e. when injecting the object context into the account controller when injecting the account controller into the membership provider. And I don't seem to have that...

Work-arounds I thought of (but don't really like).

  1. Don't hang MyMembershipProvider in MVC. Just pas an instance of it (behind and interface) to the controllers that need it like I do with repositories. Then Ninject will instantiate the provider per request. I don't like it because I'm sure MVC has a reason for instantiating the membership provider as a singleton.
  2. Find an event that occurs every request and call kernel.Inject again in each event. Re-initializing the provider every request is nearly equivalent to re-instantiating, except dirtier.
  3. Make a separate account repository for the membership provider to which I can bind in a different way. It doesn't seem right to change my object model because of Ninject.

Conclusion

IMHO the first work-around is the best. However, I much rather find a way to set Ninject to bind in the way I want.

What should I do?

回答1:

The .InRequestScope() bit is causing some of your objects to be Disposed (see Cache and Collect).

You need to make this (scoping by request) not happen in your provisioning of your provider's dependencies.

One way to achieve that is by having two bindings - one for the request processing branch and one for the global context, i.e., adding a When... which uses the context.ParentContext... chain to control whether it's InRequestScope() or not

Sadly I don't have time to give a full answer now and the relevant docs are out of sync with the code at present.