我正在重构一个生成小型报告的应用程序,并使其符合SOLID原则等。因此,我的所有类都遵循SR的DI,我使用app.config进行大多数参数变化。我还没有使用任何DI框架,而是在app入口点创建所有依赖类。然而,这导致了一个设计问题,我在这里进行了概括:
我可以像这样创建我的依赖项和主要的记者类:
//dependencies
var sharedDependency = new SharedDependency();
var whiteColorDependency = new ColorDependency("white");
var blueColorDependency = new ColorDependency("blue");
var config1Dependency = new MultiDependency("config1");
var config2Dependency = new MultiDependency("config2");
...
var config12Dependency = new MultiDependency("config12");
//main logic
var reporter1 = new Reporter(sharedDependency, whiteColorDependency, config1Dependency);
var reporter2 = new Reporter(sharedDependency, whiteColorDependency, config2Dependency);
var reporter3 = new Reporter(sharedDependency, whiteColorDependency, config3Dependency);
...
var reporter10 = new Reporter(sharedDependency, blueColorDependency, config10Dependency);
var reporter11 = new Reporter(sharedDependency, blueColorDependency, config11Dependency);
var reporter12 = new Reporter(sharedDependency, blueColorDependency, config12Dependency);
或者那样:
foreach (var config in configs)
{
//dependencies
var sharedDependency = new SharedDependency();
var colorDependency = new ColorDependency("color");
var configDependency = new MultiDependency("config");
//main logic
var reporter = new Reporter(sharedDependency, colorDependency, configDependency);
reporter.DoSomething();
}
(" colors"和" config"值都来自app.config文件,而不是硬编码。以上是概括,正如我所说,真正的项目有更多的依赖关系,依赖关系的依赖关系,有些比其他关系更多。)
第一种方法更有效,因为CSharedDependency只创建一次而CColorDependency只创建两次。 (它对我来说也更具可读性。)第二种是完全配置驱动,因此无需维护,并且完全可扩展。
那么,哪一个是最好的设计?
答案 0 :(得分:3)
组织应用程序以进行依赖项注入(无论是使用容器还是pure DI)的正确方法是在应用程序启动时使用Composition Root来组合应用程序的对象图。
因此,您的第一个示例看起来更符合该示例,因为您永远不会访问您的容器以在运行时创建依赖项,而是inject abstract factories来创建这些实例。
那就是说,从你的例子中不清楚你是如何组织你的应用程序的。没有组合根,你没有正确地进行依赖注入。因为你不得不问这个问题,我怀疑你没有组合根,因为你的第二个例子如果你做的话就永远不会有效。
参考文献:
https://www.kenneth-truyers.net/2014/11/18/how-to-use-pure-di/
答案 1 :(得分:3)
据我了解这个问题,关注的是,在第二种方案中,SharedDependency
被多次创建,ColorDependency
个实例的创建次数也超过了必要的次数。< / p>
我对此的第一反应是可能并不重要。如果您遵循constructors should do no work规则,则创建一些超出必要的对象很可能是您不会注意到的 - 特别是如果这些对象随后进行I / O操作。 .NET中的对象创建是 fast (并且I / O很慢)。
那就是说,“问题”可能很容易解决。
如果您希望完全配置驱动,则需要一种方法来区分各组配置值。最简单的方法是最有可能在appSettings
密钥前加上众所周知的前缀,但更健壮的方法是定义自定义配置部分。
在任何情况下,我都会假设您可以从配置系统中提取两个集合:colors
和configs
。
这样可以轻松地以配置驱动的方式创建服务:
var sharedDependency = new SharedDependency();
foreach (var color in colors)
{
var colorDependency = new ColorDependency(color);
foreach (var config in configs)
{
var configDependency = new MultiDependency(config);
//main logic
var reporter = new Reporter(sharedDependency, colorDependency, configDependency);
reporter.DoSomething();
}
}
所有这一切,在您开始重新发明轮子之前:大多数DI容器都支持通过app.config
进行配置,因此这也可能是您的选择。
再次: 说,毕竟考虑是否using a DI Container is an appropriate choice。使用基于文本的配置,您将丢失benefit of compile-time checking。您也可以轻松结束making the configuration system so complicated that code would be easier。
除非您有令人信服的理由在配置文件中配置对象图,否则请使用Pure DI。