Hi All,
We are building a WPF application using Ninject, we have a requirement
that we can scope our EventAggregator/MessageBus services to specific
parts of the application e.g. each window might want its own
aggregator so it only gets relevant messages. If we were using Unity
then this would simply be a case of using a ChildContainer and
overriding the binding for IEventAggregator, unfortunately Ninject's
ChildKernel isn't equivalent as a child's bindings won't override the
binding in the parent when a service is resolved by the parent kernel.
I've been working with scopes to see if I can achieve the required
effect and came up with the following:
var kernel = new StandardKernel();
kernel.Bind<IEventAggregator>()To<EventAggregator>().InCustomScope();
var eventAgg0 = kernel.Get<IEventAggregator>();
IResolutionRoot scope1 = new CustomScope(kernel);
var eventAgg1 = scope1.Get<IEventAggregator>();
IResolutionRoot scope2 = new CustomScope(kernel);
var eventAgg2 = scope2.Get<IEventAggregator>();
Assert.That(eventAgg0, Is.Not.SameAs(eventAgg1))
Assert.That(eventAgg0, Is.Not.SameAs(eventAgg2))
Assert.That(eventAgg1, Is.Not.SameAs(eventAgg2))
The scope is passed on the request as an inherited Parameter so newly
instantiated dependencies will also inherit the same instance.
var eventAgg0 = kernel.Get<IEventAggregator>();
IResolutionRoot scope1 = new CustomScope(kernel);
var windowVM = scope1.Get<IWindowViewModel>();
Assert.That(windowVM.EventAggregator, Is.Not.SameAs(eventAgg0))
Assert.That(windowVM.Child.EventAggregator,
Is.Not.SameAs(eventAgg0))
Assert.That(windowVM.EventAggregator,
Is.SameAs(windowVM.Child.EventAggregator))
If IResolutionRoot is also bound as follows then a CustomScope will
inject itself allowing services to be resolved later in the same
scope.
kernel.Bind<IResolutionRoot>().ToMethod(CustomScope.ResolutionRootFromRequest);
IResolutionRoot scope1 = new CustomScope(kernel);
var windowVM = scope1.Get<IWindowViewModel>();
Assert.That(windowVM.EventAggregator,
Is.SameAs(windowVM.ResolutionRoot.Get<IEventAggregator>()))
Code is here:
https://github.com/chillitom/CustomScope/blob/master/CustomScope.cs
https://github.com/chillitom/CustomScope/blob/master/CustomScopeTests.cs
https://github.com/chillitom/CustomScope/blob/master/BindingExtensions.cs
- What does the Ninject community think of this approach?
- Are there any serious issues or shortcomings?
- Can this be achieved more easily in another way?
- If this is useful, could it be named better? Any suggestions?
Thanks,
Tom.