Ninject:注入两个相同类型的不同对象
如果我有一个类,它具有相同类型的双重依赖(需要两个不同的实例),如果实例之间的唯一区别是更深的依赖,那么让Ninject执行DI并保持两个图分开的最佳方法是什么?
示例对象图:
foo → ClassA → ClassB bar → ClassA → ClassB
C
类的构造函数:
public class C { public C(ClassB foo, ClassB bar) { … } }
那么我如何确保用foo
实例化的ClassB
作为ClassB
依赖foo
,并且bar
… bar
?
仅仅是为了某些背景,我有一些需求变化,所以我需要用复合只写存储库替换只写存储库(IAdd)
public class CompositeWriteRepository : IAdd { public CompositeWriteRepository(IAdd foo, IAdd bar, Func descriminator) { ... } public Add(T entity) { if (descriminator(entity)) { foo.Add(entity); } else { bar.Add(entity); } } }
通过模拟,这很容易,我可以使用名称注入:
kernel.Bind<IAdd>().To().Named("foo"); kernel.Bind<IAdd>().To().Named("bar"); kernel.Bind<IAdd>().To<CompositeWriterRepository>() .WithConstructorArgument("foo", x => x.Kernel.Get<IAdd>("foo") .WithConstructorArgument("bar", x => x.Kernel.Get<IAdd>("bar");
当我使用真正的存储库时,问题出现了; foo
和bar
最终写入文件,因此需要不同的文件名。 由于它们是StreamWriter
存储库,因此它们的一个依赖项实际上获得了两个不同的文件名。
string FileName → FileStreamWriterFactory → StreamRepository → CompositeRepository
到目前为止,我发现构建东西的唯一方法是创建一个名为FileName
名为FileStreamWriterFactory
FileName
,名为StreamRepository
×2(一次用于foo
,一次用于bar
)。 这似乎很多工作,所以我希望有更好的解决方案。
如果需要,我可以重新设计,感觉就像是一种优雅的方式,可以在需求变化时快速添加分隔条目。 我意识到我的课程都非常具体,但我认为单一的责任通常会支持这一点,在我的情况下,我们编写了一堆小应用程序,并且我们可以满足更多的请求,因此它是一个很好的方法来获得大量的可重用代码我基本上只需要重新配置不同的任务。
解
雷莫格洛尔应该获得信誉; 他可能是最好的做法。
我实际上做的是创建一个新的扩展
public static bool WhenAnchester(this IRequest request, Func conditions) { var parentContext = request.ParentContext; if (parentContext == null) { return false; } return conditions(parentContext.Request) || parentContext.Request.WhenAnchester(conditions); }
然后,我可以轻松控制将哪个文件注入哪个存储库。
kernel.Bind().ToConstant("Foo.txt") .When(x => x.Target.Name == "filepath" && x.WhenAnchester(t => t.Target != null && t.Target.Name == "Dest1")); kernel.Bind().ToConstant("Bar.txt") .When(x => x.Target.Name == "filepath" && x.WhenAnchester(t => t.Target != null && t.Target.Name == "Dest2"));
可能有一个更好的解决方案,所以我不需要为其他人推荐这个,但它对我来说效果很好。
是的,有更好的方法
请参阅https://github.com/ninject/ninject/commit/60443badf4ef840531c93e9287b154a9bba337c2
它是3.0,但IsAnyAnchestorNamed也可以与When条件中的2.2一起使用。