Reputation: 103
I'm developing a WPF application which has a big part of business logic and data processing. According to idea of using IoC I've decided to use Ninject as dependency injector for this part of logic and data processing.
I've initialized the kernel of ninject and binded the interfaces with the concrete classes in the App.xaml.cs
file (i.e. in the default app class). So far everything is fine.
The problem is that somewhere in my application I need two concrete instances of a class (that I do not want to pass as parameter in the constructor). Actually what I need to do is:
var instance1 = kernel.Get<IClassName>();
The problem is that I've no access to kernel
(concrete instance of the Ninject kernel).
I know that in ASP.NET MVC I could do something like
var instance1 = (IClassName)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(IClassName));
Is there something analogous that I can use? Or am I forced to solve the problem with a service locator pattern (about which I know there is conflicting opinions)?
Upvotes: 1
Views: 578
Reputation: 13233
How about using Ninject.Extensions.Factory for the instantiation of said dependencies?
You can inject a Func<T>
and when you later call it, it will return a newly instantiated T
. There's also Lazy<T>
in case you just want to late-instantiate a single instance "on first usage".
Then again you can also define interface factories like:
public interface IFooFactory
{
IFoo Create();
}
with corresponding bindings:
Bind<IFooFactory>().ToFactory();
Bind<IFoo>().To<Foo>(); // add Singleton, or ToMethod binding,.. or whatever you require
Upvotes: 0
Reputation: 56869
Since you want to use more than one dependency per class, you should look to design patterns rather than the DI container to solve your problem.
There are at least a couple of options. Here is some basic framework to setup the scenario:
public interface IPresenter
{
void Present();
}
public interface IConsumer
{
void DoSomething();
}
public class SomeConsumer : IConsumer
{
private readonly IPresenter presenter;
public SomeConsumer(IPresenter presenter)
{
if (presenter == null)
throw new ArgumentNullException("presenter");
this.presenter = presenter;
}
public void DoSomething()
{
this.presenter.Present();
}
}
You could use the composite pattern, in which you could then order the presenters in a list.
public class Presenter1 : IPresenter
{
public void Present()
{
// Do something here
}
}
public class Presenter2 : IPresenter
{
public void Present()
{
// Do something here
}
}
public class Presenter3 : IPresenter
{
public void Present()
{
// Do something here
}
}
public class CompositePresenter : IPresenter
{
private readonly IPresenter[] presenters;
public CompositePresenter(IPresenter[] presenters)
{
if (presenters == null)
throw new ArgumentNullException("presenters");
this.presenters = presenters;
}
public void Present()
{
// Do nothing except delegate the call to the nested
// instances. You may need to do some extra work to deal
// with multiple return values, like add up the values
// or decide which value works best for the scenario.
foreach (var presenter in this.presenters)
{
presenter.Present();
}
}
}
And then wire it up like:
var presenter1 = new Presenter1();
var presenter2 = new Presenter2();
var presenter3 = new Presenter3();
var compositePresenter = new CompositePresenter(new IPresenter[] {
presenter1,
presenter2,
presenter3
});
var consumer = new SomeConsumer(compositePresenter);
In Ninject, the above would look like:
var kernel = new StandardKernel();
kernel.Bind<Presenter1>().ToSelf();
kernel.Bind<Presenter2>().ToSelf();
kernel.Bind<Presenter3>().ToSelf();
kernel.Bind<IPresenter>().To<CompositePresenter>()
.WithConstructorArgument("presenters",
new IPresenter[] {
kernel.Get<Presenter1>(),
kernel.Get<Presenter2>(),
kernel.Get<Presenter3>()
});
// When SomeConsumer is injected into a constructor, its IPresenter
// dependency will be wired as shown with the new keyword example above.
Or you could use a decorator pattern:
public class Presenter1 : IPresenter
{
public Presenter1(IPresenter innerPresenter)
{
if (innerPresenter == null)
throw new ArgumentNullException("innerPresenter");
this.innerPresenter = innerPresenter;
}
public void Present()
{
// Do something here
// You could make this call conditional
this.innerPresenter.Present();
// Or do something here
}
}
public class Presenter2 : IPresenter
{
public Presenter2(IPresenter innerPresenter)
{
if (innerPresenter == null)
throw new ArgumentNullException("innerPresenter");
this.innerPresenter = innerPresenter;
}
public void Present()
{
// Do something here
// You could make this call conditional
this.innerPresenter.Present();
// Or do something here
}
}
public class Presenter3 : IPresenter
{
public Presenter3(IPresenter innerPresenter)
{
if (innerPresenter == null)
throw new ArgumentNullException("innerPresenter");
this.innerPresenter = innerPresenter;
}
public void Present()
{
// Do something here
// You could make this call conditional
this.innerPresenter.Present();
// Or do something here
}
}
public class NullPresenter : IPresenter
{
public void Present()
{
// Do nothing here - this class is a placeholder
// in case you want to expand the design later
}
}
And then wire it up like:
var nullPresenter = new NullPresenter();
var presenter3 = new Presenter3(nullPresenter);
var presenter2 = new Presenter2(presenter3);
var presenter1 = new Presenter1(presenter2);
var consumer = new SomeConsumer(presenter1);
In Ninject, the above would look like:
var kernel = new StandardKernel();
kernel.Bind<IPresenter>().To<NullPrenter>().WhenInjectedInto<Presenter3>();
kernel.Bind<IPresenter>().To<Presenter3>().WhenInjectedInto<Presenter2>();
kernel.Bind<IPresenter>().To<Presenter2>().WhenInjectedInto<Presenter1>();
kernel.Bind<IPresenter>().To<Presenter1>();
// When SomeConsumer is injected into a constructor, its IPresenter
// dependency will be wired as shown with the new keyword example above.
The advantage of using design patterns is that you end up with loosely coupled code that is totally modular, extensible, and even independent of the DI container.
Upvotes: 1