我正在使用Ninject 3.0.1.10和来自NuGet的ninject.extensions.factory 3.0.1.0 - 在“真实”场景中我将使用ninject.extensions.conventions(而不是手动绑定IFoo),但我想保持这一点,试图简化问题 .
我有一个IFoo接口和它的多个实现,每个都在子命名空间和子文件夹下,名为Gen1和Gen2 . 我有一个IFooFactory接口,其意图是它根据指定的参数(字符串,枚举,等等)返回一个IFoo .
我在这个例子中使用枚举只是为了尝试使其更清晰 - 我最初创建了一个字符串版本,但感觉就像传递更多任意参数(例如字符串)的异议只会混淆问题 .
public enum ImplementationGeneration
{
Gen1,
Gen2,
Gen3,
}
public interface IFoo
{
void DoStuff();
}
public interface IFooFactory
{
IFoo CreateFoo(ImplementationGeneration implementationGeneration);
}
namespace SomeRootNamespace.Gen1
{
public class Foo : IFoo
{
public void DoStuff()
{
Console.WriteLine("Doing Type1 stuff");
}
}
}
namespace SomeRootNamespace.Gen2
{
public class Foo : IFoo
{
public void DoStuff()
{
Console.WriteLine("Doing Type2 stuff");
}
}
}
现在,我理解让消费者'选择'这样的实现是一种理想情况下不存在的耦合形式,但恕我直言,它与Ninject已经支持的命名绑定具有相同的耦合级别 . 我想避免将属性添加到实现中,并且在工厂界面中使用GetGen1 / GetGen2 / etc方法是非常适合的,因为我最终通过某个开关违反OCP以将输入映射到要调用的方法(或手动使用反射)
我现在所拥有的完整/工作代码,如果可能的话,我宁愿避免使用:https://gist.github.com/4549677
它使用两种方法:
-
一个手动工厂实现,违反了OCP并且传递了枚举的枚举
-
使用带有IInstanceProvider实例的工厂扩展(子类StandardInstanceProvider来覆盖GetInstance) .
第二种方法似乎可以“接近”'正确的方式'来实现这一点,但是1)它保留了对内核的引用以便完成它的工作,这可能是一个坏主意,2)因为在调用期间搜索所有IFoo绑定时,我无法在IFoo的绑定中找到具体类型,它当前执行GetAll,因此它实例化N-1个实例,而不是此场景需要的实例 .
1 回答
好吧,我发现的东西至少比我上面的东西好 .
它毕竟使用命名绑定,_1496119用于根据命名空间的最后部分命名所有绑定 . 这最终会将名称附加到许多绑定中,这些绑定不会导致其使用中出现任何问题(至少在我的测试中) .
如果由于某种原因对于将来遇到这种问题的人来说是一个问题,你可以在通过约定设置绑定的代码中更加具体 - 例如,如果最后一个命名空间部分位于特定设置或匹配特定模式 .
然后使用the UseFirstArgumentAsNameInstanceProvider根据工厂方法的第一个参数查找绑定名称(因此您不必与链接的Wiki页面相同) .
我有一个不同的/更好的选择,但至少这似乎是合理的,并没有任何明显的问题 . :)