我正在开发一个WPF应用程序,它具有很大的业务逻辑和数据处理能力。 根据使用IoC的想法,我决定将Ninject用作这部分逻辑和数据处理的依赖注入器。
我初始化了ninject的内核,并使用App.xaml.cs
文件中的具体类(即默认的app类)绑定了接口。到目前为止一切都很好。
问题是在我的应用程序的某个地方我需要一个类的两个具体实例(我不想在构造函数中作为参数传递)。 其实我需要做的是:
var instance1 = kernel.Get<IClassName>();
问题是我无法访问kernel
(Ninject内核的具体实例)。
我知道在ASP.NET MVC中我可以做类似
的事情var instance1 = (IClassName)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(IClassName));
我可以使用类似的东西吗? 或者我是否被迫用服务定位器模式来解决问题(我知道存在相互矛盾的意见)?
答案 0 :(得分:1)
由于您希望每个类使用多个依赖项,因此您应该设计模式而不是DI容器来解决您的问题。
至少有几种选择。以下是设置场景的一些基本框架:
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();
}
}
您可以使用composite pattern,然后您可以在列表中订阅演示者。
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();
}
}
}
然后将它连接起来:
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);
在Ninject中,上面的内容如下:
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.
或者您可以使用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
}
}
然后将它连接起来:
var nullPresenter = new NullPresenter();
var presenter3 = new Presenter3(nullPresenter);
var presenter2 = new Presenter2(presenter3);
var presenter1 = new Presenter1(presenter2);
var consumer = new SomeConsumer(presenter1);
在Ninject中,上面的内容如下:
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.
使用设计模式的优势在于您最终得到的松散耦合代码完全模块化,可扩展,甚至独立于DI容器。
答案 1 :(得分:0)
如何使用Ninject.Extensions.Factory来实例化所述依赖项?
您可以注入Func<T>
,当您稍后调用它时,它将返回一个新实例化的T
。还有Lazy<T>
以防你想要在第一次使用&#34;后期实例化单个实例&#34;
然后,您还可以定义接口工厂,如:
public interface IFooFactory
{
IFoo Create();
}
带有相应的绑定:
Bind<IFooFactory>().ToFactory();
Bind<IFoo>().To<Foo>(); // add Singleton, or ToMethod binding,.. or whatever you require