SRP,DI和app.config:什么时候实例化注入类?

时间:2016-01-31 04:53:20

标签: c# dependency-injection configuration-files solid-principles single-responsibility-principle

我正在重构一个生成小型报告的应用程序,并使其符合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只创建两次。 (它对我来说也更具可读性。)第二种是完全配置驱动,因此无需维护,并且完全可扩展。

那么,哪一个是最好的设计?

2 个答案:

答案 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密钥前加上众所周知的前缀,但更健壮的方法是定义自定义配置部分。

在任何情况下,我都会假设您可以从配置系统中提取两个集合:colorsconfigs

这样可以轻松地以配置驱动的方式创建服务:

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