C# 对内部对象使用IoC

C# 对内部对象使用IoC,c#,inversion-of-control,ninject,C#,Inversion Of Control,Ninject,我目前正在为我使用的一个程序编写一个开源SDK,并在内部使用IoC容器(NInject)来连接我所有的内部依赖关系 我有一些标记为内部的对象,这样我就不会拥挤公共API,因为它们只在内部使用,用户不应该看到,比如工厂和其他对象。我遇到的问题是NInject无法创建内部对象,这意味着我必须将所有内部对象标记为公共对象,这会阻塞公共API 我的问题是:有没有办法解决这个问题,还是我做错了 另外,我曾考虑过使用InternalsVisiableTo属性,但我觉得这有点异味。我想你甚至不需要它。国际奥委

我目前正在为我使用的一个程序编写一个开源SDK,并在内部使用IoC容器(NInject)来连接我所有的内部依赖关系

我有一些标记为内部的对象,这样我就不会拥挤公共API,因为它们只在内部使用,用户不应该看到,比如工厂和其他对象。我遇到的问题是NInject无法创建内部对象,这意味着我必须将所有内部对象标记为公共对象,这会阻塞公共API

我的问题是:有没有办法解决这个问题,还是我做错了


另外,我曾考虑过使用InternalsVisiableTo属性,但我觉得这有点异味。

我想你甚至不需要它。国际奥委会是为公众服务的。直走去


但是-这只是我的直觉…

创建一个与外部API不同的二级内部API。您可能需要手动执行拆分…

您可以

  • 修改Ninject
  • 选择一个不同的容器

快速查看其他答案:看起来您所做的事情并没有如此不同,以至于Ninject存在根本性的问题,您需要对其进行修改或更换。在许多情况下,您不能“直接进入内部”,因为它们依赖于未解决的依赖注入;因此,首先使用Ninject。另外,听起来你已经有了一套内部接口,这就是为什么这个问题被提出的原因

想法:在SDK或库中直接使用Ninject的一个问题是,用户必须在代码中使用Ninject。这可能不是你的问题,因为这是你的国际奥委会的选择,所以你无论如何都要使用它。如果他们想使用另一个IoC容器,那么现在他们实际上有两个正在运行的复制工作。更糟糕的是,如果他们想使用Ninject v2,而您已经使用了v1.5,那么情况会变得更加复杂

最佳情况:如果可以重构类,使它们通过依赖项注入获得所需的一切,那么这是最干净的,因为库代码不需要任何IoC容器。该应用程序可以连接依赖项,它只是流动。但这并不总是可能的,因为有时库类需要创建具有依赖项的实例,而这些依赖项不能通过注入来解析

建议:的(和它的)是专门为这种情况设计的(具有依赖关系的库)。您针对CommonServiceLocator编写代码,然后应用程序指定哪个DI/IoC实际支持接口


这有点痛苦,因为现在你的应用程序中必须有Ninject和CommonServiceLocator,但是CommonServiceLocator非常轻量级。您的SDK/库代码只使用了相当干净的CommonServiceLocator。

我将投票支持InternalsVisibleTo解决方案。完全没有味道,真的。该属性的要点是启用您想要的那种行为,因此,与其跳过各种复杂的限制,让事情在没有它的情况下正常工作,不如使用框架提供的功能来解决这个特定问题


我还建议,如果您想对用户隐藏您对容器的选择,请使用将Ninject程序集与SDK程序集组合起来,并应用/internalize参数将Ninject程序集的可见性更改为internal,这样Ninject命名空间就不会泄漏出您的库(很抱歉,无法在线找到ILMerge文档的链接,但下载中有一个文档文件)。还有一个关于将ILMerge集成到构建过程中的问题。

如果是开源SDK,我想知道你为什么试图阻止使用你的代码?我理解你是否试图确保我们SDK“用户”不要错误地实例化对象,但对我来说,这更像是一种气味(SRP,LSP)。你能解释更多的约束吗?