-
Notifications
You must be signed in to change notification settings - Fork 6
InNamedScope
The notion of a Named Scope is the most general and powerful facility offered in this Extension -- the other facilities are actually implemented using the Named Scope mechanism.
A Named Scope lets you specify on a Bind
ing that objects created via the Binding are to act as the Scope Object for other objects that are generated as part of the work of Composing the object graph for a given Get<T>()
Resolve Request.
The facility consists of two Extension Methods
-
DefinesNamedScope(string scopeName)
. This identifies theBind
ing as creating a Scope which can be referred to in otherBind
ings. Only a single instance of a service scoped in this manner will be created per Object Graph being Composed (each Composition in the Composition Root (e.g. viaKernel.Get<T>()
will generate a separately isolated instance) -
InNamedScope(string scopeName)
. This constrains all resolutions of the Service Type being bound to produce a single shared instance which will be yielded as part of any Resolve within a given Object Graph Composition. (TODO verify) Note that anException
will be thrown if a Resolve has not yet had cause to visit a Binding that employsDefinesNamedScope()
to establish the Named Scope with the citedscopeName
earlier in the Object Graph Composition.
Scenario 1: Sheet implementation with collaborating components sharing a single Sheet Data Repository per Sheet object within a single Object Graph Composition
Lets examine how this works using an example scenario. Imagine that you are creating an Excel-like application that has multiple worksheets. As part of the implementation, you have multiple components (e.g. the data repository) that have a worksheet as their Scope and need to be accessible to several other components.
To be more concrete you might have a Sheet
implementation which relies on two collaborating components -- one to draw the sheet (SheetPresenter
) and one to update the calculated values on each cell (SheetCalculator
). These two parts of the overall Sheet code each have a dependency on SheetDataRepository
and the same instance needs to be supplied to each one. One can’t simply Bind...().To<SheetDataRepository>().InSingletonScope()
because you need to be able have multiple sheets in the system. In this case the Bind
ings can be specified as follows in order to have the Sheet
instance act as the Scope relative to which a single SheetDataRepository
instances is created and shared for subsequent usages within the Object Graph being Composed:
const string ScopeName = "Sheet"; Bind<Sheet>().ToSelf().DefinesNamedScope(ScopeName); Bind<SheetDataRepository>().ToSelf().InNamedScope(ScopeName); Bind<SheetPresenter>().ToSelf(); Bind<SheetCalculator>().ToSelf();
Scenario 2: Deferred Creation of Services via Factories that require Shared Objects from the Initial Object Graph
In conjunction with Ninject.Extensions.ContextPreservation
this Scope type can also be used for instances that are not created as direct dependency within a single Object Graph Composition, but at a later point in time by a (possibly generated) Factory that was Resolved as a dependency in the initial Object Graph Composition.
Extending Scenario #1, lets say SheetCalculator
gets a Factory (CellCalculatorFactory
) injected with a CreateCellCalculator()
method that is used by the SheetCalculator
to create a CellCalculator
whenever a formula is added to a cell. However, the CellCalculator
of course needs to gain access to a SheetDataRepository
-- the single one that was generated in the initial Object Graph Composition.
This scenario can be modelled using the following Bind
ing structure:
this.kernel.Load(new NamedScopeModule()); this.kernel.Load(new ContextPreservationModule()); const string ScopeName = "Sheet"; Bind<Sheet>().ToSelf().DefinesNamedScope(ScopeName); Bind<SheetDataRepository>().ToSelf().InNamedScope(ScopeName); Bind<SheetPresenter>().ToSelf(); Bind<SheetCalculator>().ToSelf(); Bind<CellCalculatorFactory>().ToSelf(); Bind<CellCalculator>().ToSelf();
- Home
- Applied mechanisms: InCallScope, InParentScope
- Architectural discussion: Child Kernel versus Named Scope
- Low level programmatic mechanism: CreateNamedScope/GetScope