首先,我使用Simple Injector,但我认为这个问题适用于任何DI框架。
在创建要为应用程序注册的服务时,将服务容器通过其构造函数传递给服务是否被视为不良做法?
例如。请考虑以下代码。
//IServiceInterface.cs
interface IServiceInterface {}
//MyService.cs
//All standard using statements here...
using SimpleInjector;
class MyService : IServiceInterface
{
private _container {get; set;}
public MyService(Container container)
{
_container = container;
//Construct!
}
}
//MyApp.cs
public Contrainer container;
....
//My application bootstrapper method
void Bootstrap()
{
var container = new Container();
container.RegisterSingle<IServiceInterface >(() => new MyService(container));
container.Verify();
this.container = container;
}
从上面的方法可以看出,我定义了一个采用Simple Injector容器的服务类。当我注册容器时,我将与我的应用程序关联的容器传递给服务。
当您定义一个服务时,这似乎是一种有用的方法,该服务将位于一个单独的项目中,甚至可能位于不同的名称空间中,需要在应用程序生命周期的某个时刻注册新服务。但是,我没有在任何例子中看到过这种情况,在我尝试这样的事情之前,我想确保这种方法是正确的。
这种行为被认为是良好的DI练习吗?如果没有,您如何获得应用程序DI容器,并在服务中注册需要的新服务?
更新 - 其他详细信息
由于两个原因,我决定开始使用依赖注入来创建一个新项目。一,这是一个庞大的项目,可能包括10-12个Visual Studio项目,其次,许多这些项目包含我多年来从一个应用程序复制并粘贴到另一个应用程序的代码,然后稍微修改了它们需要的。足够的,现在是时候编写我自己的业务逻辑框架,与我们公司合作,正如我们所需要的那样。
这个第一个大项目似乎是从DI和我的自制框架开始的地方。为了一次构建和测试这个应用程序,我定义了很多接口和“shell”服务类。这样,我就可以连接我的顶级应用程序,并在项目完成后更新依赖项并链接到我的解决方案中。
由于这是一个如此大的应用程序,我有服务,需要依赖服务......这将进一步依赖于服务。
我的想法是我的应用程序应该只注册验证用户身份和加载视图所需的服务。 View服务应该注册Model视图。 ModelView服务应该注册它们相关的Model服务,它将注册数据库连接服务......叹息,它将EVENTUALLY注册服务器端同步服务,该服务将注册本地数据库连接服务和Web应用程序服务。唷!声音混乱?嗯,有点儿。
我的想法是我可以定义这些可以接受Container对象的类,然后每个服务都将使用容器来获取可能已经存在的任何底层服务,或者如果尚未创建一个新实例,则实例化它。
对于instane,我的用户Auth服务可以通过应该与我的Model服务共享的ILocalDB
服务来缓存信息。如果我在启动应用程序时注册所有这些服务,那么应用程序将会缓慢,整个注册看起来会非常粗糙。
我认为必须有一个优雅的解决方案。我错过了什么?
答案 0 :(得分:3)
在我看来,传递容器并不是好设计。您实际上是在传递一个通用对象构造工厂,因此绕过了明确关于依赖关系的固有价值。在实践中,您也可以在Service类上声明container
的静态属性。
如果我需要动态构造对象,我通常会传入工厂而不是显式实例。比如,传入ILogFactory而不仅仅是ILog的一个实例。这使得从代码中可以看出动态构造的是什么,代价是一些工厂和构造函数参数。
另一种选择,如果你不需要创建多个依赖项实例,但是你知道你只需要其中的一些,那就是确保对象构造很轻。然后,明确声明所有依赖项并不重要,因为只有在实际使用它们时它们才会发生成本。
答案 1 :(得分:2)