What is the difference between “scope”, “context”, etc. In Ninject?

Can the Ninject concepts scope , context , name , (and activation block ?) Be separated and clearly explained at a conceptual level?

As an example, I have a service that loads data records from a database, and for each record it creates a “worker” through the Ninject factory extension. Both the service and individual employees use the Entity Framework object context to interact with the database. ObjectContext is introduced through the constructor for both (as well as for other common dependencies). It is currently single-threaded, but ultimately workers must run in their threads in parallel, and so they will need their own instance of ObjectContext and an explicit start / delete life cycle. An instance of the ObjectContext must be used together for the duration of the working "unit of work" (and therefore is not temporary, because it is entered into several repositories used by the worker). I'm stuck trying to get this functionality.

I naively wanted something similar (using named scope and keeping the context ):

Bind<MyDbContext>().ToSelf(); Bind<MyService>().ToSelf(); Bind<IWorkerFactory>().ToFactory().InThreadScope(); // scope prob not necessary Bind<MyWorker().ToSelf().DefinesNamedScope("workerScopeName"); Bind<MyDbContext>().ToSelf().InNamedScope("workerScopeName"); 

This is obvious (at least obvious to Ninject users), resulting in a "More than one binding ..." error due to MyDbContext. After reading a lot more, I now think that probably I would use the binding names for the worker and ObjectContext. I think I still need a scope so that I can explicitly dispose of the ObjectContext when the worker has finished (and it removes the method from the ninject scope).

In any case, I still mostly guess, and I am posting this question in the hope that someone will be able to clarify these concepts in Ninject.

+6
source share
1 answer

Context: Meta information for the current resolution. It determines where in the tree of objects the current allowed object will be entered. (for example, the object currently resolved will be introduced into the constructor of class A, which is introduced into class B, ....) It can be used, for example, to determine whether binding is applied in the current context using one of the When overloads . It is also passed to many other callbacks in free syntax (e.g. InScope, OnActivation, ....)

Scope: Defines the life cycle of an object and reuse of an existing instance. There are many predefined areas, as well as a general one, which can determine the scope from the current context ( InScope(ctx => ... )

Named binding: Meta information about the binding. It can be used in combination with context. For instance. A binding only applies when in the current context any of the parent bindings has a name.

Activation block: (compared to Ninject 2.x - 3.x this is likely to change in future versions). Inside the activation block, each binding changes so that the activation block is like a scope. This means that the area specified in the binding will be ignored. Exactly one instance will be created for resolution on one activation unit.

I personally will not use this function because it is erroneous, ignoring all kinds of other areas, for example InSingletonScope . It is better to use the areas defined by Ninject.Extensions.NamedScope.

As for your example: since you have two MyDbContext bindings, you will need to add conditions to them. e.g. WhenAnyAncestorNamed . Or you can use another Scope, such as InCallScope() , with one binding.

+9
source

All Articles