C# SRP、DI和app.config:何时实例化注入类?
我正在重构一个小型的报表生成应用程序,使其遵循可靠的原则,等等。因此,我所有的类都遵循带有DI的SRP,我使用app.config处理大多数参数变化。我还没有使用任何DI框架,而是在应用程序入口点创建所有依赖类。然而,这导致了一个设计问题,我在这里概括如下: 我可以像这样创建依赖项和主报告器类:C# SRP、DI和app.config:何时实例化注入类?,c#,dependency-injection,configuration-files,solid-principles,single-responsibility-principle,C#,Dependency Injection,Configuration Files,Solid Principles,Single Responsibility Principle,我正在重构一个小型的报表生成应用程序,使其遵循可靠的原则,等等。因此,我所有的类都遵循带有DI的SRP,我使用app.config处理大多数参数变化。我还没有使用任何DI框架,而是在应用程序入口点创建所有依赖类。然而,这导致了一个设计问题,我在这里概括如下: 我可以像这样创建依赖项和主报告器类: //dependencies var sharedDependency = new SharedDependency(); var whiteColorDependency = new Col
//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();
}
?
(颜色和配置值都来自app.config文件,不是硬编码的。正如我所说,上面是泛化的,真实的项目有更多的依赖关系,依赖关系的依赖关系,其中一些比其他的更共享。)
第一种方法更有效,因为CSharedDependency只创建一次,CColordDependency只创建两次。第二个是完全配置驱动的,因此不需要维护,并且完全可扩展
那么,哪一种设计是最好的呢?组织应用程序进行依赖项注入的正确方法(无论是使用容器还是容器)是在应用程序启动时使用一个来组成应用程序的对象图 因此,您的第一个示例看起来更符合这一点,因为您永远不会在运行时访问容器来创建依赖项,而是创建这些实例 也就是说,从您的示例中不清楚您是如何组织应用程序的。如果没有组合根,则无法正确执行依赖项注入。既然你不得不问这个问题,我怀疑你没有合成根,因为如果你有,你的第二个例子就永远不会起作用 参考资料:
组织应用程序进行依赖项注入(无论是使用容器还是容器)的正确方法是在应用程序启动时使用来组成应用程序的对象图 因此,您的第一个示例看起来更符合这一点,因为您永远不会在运行时访问容器来创建依赖项,而是创建这些实例 也就是说,从您的示例中不清楚您是如何组织应用程序的。如果没有组合根,则无法正确执行依赖项注入。既然你不得不问这个问题,我怀疑你没有合成根,因为如果你有,你的第二个例子就永远不会起作用 参考资料:
据我所知,问题在于在第二个备选方案中,
SharedDependency
被多次创建,而且ColorDependency
实例的创建次数也超过了必要的次数
我对此的第一反应是,这可能无关紧要。如果您遵循这样的规则,创建一些超出需要的对象很可能是您不会注意到的—特别是当这些对象随后参与I/O时。在.NET中创建对象很快(而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
进行配置,因此这可能也是你的一个选择
又一次:那就说,考虑一下到底是不是。使用基于文本的配置,您将丢失。你也可以很容易地结束
除非您有令人信服的理由在配置文件中配置对象图,否则请支持。据我理解,这个问题的关键在于,在第二个备选方案中,
SharedDependency
被多次创建,而且ColorDependency
实例的创建次数也超过了必要的次数
我对此的第一反应是,这可能无关紧要。如果您遵循这样的规则,创建一些超出需要的对象很可能是您不会注意到的—特别是当这些对象随后参与I/O时。在.NET中创建对象很快(而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
进行配置,因此这可能也是你的一个选择
又一次:那就说,考虑一下到底是不是。使用基于文本的配置,您将丢失。你也可以很容易地结束
除非您有令人信服的理由在配置文件中配置对象图,否则请支持。如果您查看您提供的参考资料中的“控制台应用程序中的纯DI”部分,这正是我所拥有的:在main()中有一个具有纯DI和依赖项构造的控制台应用程序。“entryPoint.Run()”基本上是我的“reporter.DoSomething()”。唯一的di