我正在为我使用的程序编写一个开源SDK,我正在内部使用IoC容器(NInject)来连接所有内部依赖项。
我有一些被标记为内部的对象,因此我不会挤占公共API,因为它们仅在内部使用,并且不应该被用户看到,例如工厂和其他对象。我遇到的问题是NInject无法创建内部对象,这意味着我必须将所有内部对象标记为公共API。
我的问题是:有什么方法可以解决这个问题,还是我做错了?
PS。我曾考虑使用InternalsVisiableTo属性,但我觉得这有点气味。
答案 0 :(得分:3)
快速查看其他答案:看起来你似乎没有做出如此不同的事情,以至于Ninject存在根本性的错误,你需要修改或替换它。在许多情况下,你不能“直接进入内部”,因为它们依赖于未解决的依赖注入;因此首先使用Ninject。另外,听起来你已经有了一套内部接口,这就是提出这个问题的原因。
思考:直接在SDK或库中使用Ninject的一个问题是,您的用户必须在其代码中使用Ninject。这对您来说可能不是问题因为它是您的IoC选择,所以无论如何您都要使用它。如果他们想要使用另一个IoC容器,那么现在他们实际上有两个正在运行的重复工作。更糟糕的是,如果他们想要使用Ninject v2并且你已经使用了v1.5那么那真的会使情况变得复杂。
最好的情况:如果您可以重构您的类,以便通过依赖注入获得所需的一切,那么这是最干净的,因为库代码不需要任何 IoC容器。该应用程序可以连接依赖项,它只是流动。但这并不总是可行,因为有时库类需要创建具有您无法通过注入解析的依赖项的实例。
建议: CommonServiceLocator(及其the Ninject adapter)是专为此情况设计的(具有依赖项的库)。您对CommonServiceLocator进行编码,然后应用程序指定哪个DI / IoC实际支持该接口。
现在您必须在应用程序中使用Ninject 和 CommonServiceLocator,但是CommonServiceLocator非常轻量级,这有点令人痛苦。您的SDK /库代码仅使用相当干净的CommonServiceLocator。
答案 1 :(得分:0)
我猜你甚至不需要那个。 IoC是公共的东西。直接进入内部。
但是 - 这只是我的直觉......
答案 2 :(得分:0)
创建一个与外部API不同的辅助内部API。您可能需要手动进行拆分......
答案 3 :(得分:0)
我要投票给InternalsVisibleTo解决方案。完全没有气味,真的。该属性的要点是启用您想要的行为类型,因此,不要跳过各种精心设计的环节以使其无需工作,只需使用框架提供的功能来解决此特定问题。
我还建议,如果要隐藏用户选择的容器,请使用ILMerge将Ninject程序集与SDK程序集合并,并应用 / internalize 参数将Ninject程序集的可见性更改为内部,因此Ninject名称空间不会泄漏到您的库中(抱歉,无法在线找到ILMerge文档的链接,但下载中有一个doc文件)。关于将ILMerge集成到构建过程中还有nice blog post。
答案 4 :(得分:-1)
你可以