开放泛型的 DI 绑定是反模式吗?

Mei*_*hes 1 c# generics dependency-injection ninject inversion-of-control

这个例子为例:

Bind(typeof(IRepository<>)).To(typeof(Repository<>));
Run Code Online (Sandbox Code Playgroud)

这对 NInject 有效,我的问题是这是否是滥用/反模式。

这样做的问题是您不能拥有 IRepository<> 类型的成员/参数变量,因此拥有此绑定实例的唯一方法是通过带有类型请求的工厂。IE

_kernel.Get(typeof(IRepository<>));
Run Code Online (Sandbox Code Playgroud)

一种可能的探索途径可能是使用动力学;

public Foo(IRepository<dynamic> repository)
{}
Run Code Online (Sandbox Code Playgroud)

至少在这里我们有一个构造函数参数被注入,它遵循控制反转。

我问上述问题是因为我问过关于开放泛型的另一个问题;在这种情况下,以下...

public Foo(IEnumerable<IRepository<dynamic>> allRepoInstancesInjected)
Run Code Online (Sandbox Code Playgroud)

......似乎应该是可能的。

Rem*_*oor 5

我认为您误解了开放通用绑定的工作原理。

您无法使用_kernel.Get(typeof(IRepository<>));This 来解析开放泛型,这只会引发异常。您也无法枚举所有可能的封闭泛型。或者您期望IEnumerable<IList<T>>返回什么?IList与地球上曾经和将要实现的所有类相结合的枚举?

您可以使用它们来获得明确指定的封闭泛型。例如,不是定义应用程序中使用的所有封闭泛型,例如:

Bind(typeof(IRepository<Foo>)).To(typeof(Repository<Foo>));
Bind(typeof(IRepository<Bar>)).To(typeof(Repository<Bar>));
Bind(typeof(IRepository<Baz>)).To(typeof(Repository<Baz>));
Run Code Online (Sandbox Code Playgroud)

你只需定义一次

Bind(typeof(IRepository<>)).To(typeof(Repository<>));
Run Code Online (Sandbox Code Playgroud)

然后你可以将它们作为封闭的通用依赖项

ctor(IRepository<Foo> fooRepository)
Run Code Online (Sandbox Code Playgroud)

我没有看到任何反对模式 DI 的东西。如果通用存储库是反模式是另一个问题,但不是这个问题的一部分。

并获得开放泛型的动态确实有效

ctor(IRepository<dynamic> dynamicRepository)
Run Code Online (Sandbox Code Playgroud)