常用对象具有配置依赖性

Sne*_*nea 2 c# configuration design-patterns dependency-injection

我们的应用程序中有一个非常常见的对象.在这种情况下,我们称之为Ball.球很好,但在某些配置中,它们的行为不同.它目前设置如下:

class Ball
{
    private static readonly bool BallsCanExplode;
    static Ball()
    {
        bool.TryParse(ConfigurationManager.AppSettings["ballsCanExplode"], 
            out BallsCanExplode);
    }
    public Ball(){}
}
Run Code Online (Sandbox Code Playgroud)

这在实践中完全正常.如果配置是球可以爆炸,它们会爆炸,如果不是,则不会爆炸.问题是它完全不可测试.我无法找到一种保持可测试性的好方法,并且仍然易于实例化.

最简单的解决方案是将球和配置分离:

class Ball
{
    private readonly bool CanExplode;
    public Ball(bool canExplode);
}
Run Code Online (Sandbox Code Playgroud)

这个问题是曾经在Ball类中曾经是一个孤立的依赖,现在已经扩散到每个制作Ball的类中.如果这种依赖注入,那么爆炸球的知识必须到处注入.

BallFactory存在同样的问题.虽然每个班级都可以去new Ball(),但现在必须知道必须在任何地方注入的BallFactory.另一种选择是使用已经在应用程序中烘焙的服务定位器:

class Ball
{
    private readonly bool CanExplode;
    public Ball()
    {
        CanExplode = ServiceLocator.Get<IConfiguration>().Get("ballsCanExplode");
    }
}
Run Code Online (Sandbox Code Playgroud)

这仍然保持了球的配置依赖性,但允许注入测试配置.虽然使用了球,但是在每次new Ball()调用时找到服务似乎有点过分.

什么是保持这个可测试的最佳方法,以及易于实例化?

注意:应用程序中既有依赖注入框架又有服务定位器,它们都经常使用.

jas*_*son 5

实例化球的类应该BallFactory作为依赖项接收.BallFactory无论是否生产爆炸球或非爆炸球,都可以相应地配置为应用程序启动.

没有BallFactory读取应用程序配置文件来确定要生成哪种类型的球.应该注入BallFactory.

服务定位器是一种反模式.不要使用它们.

  • @Snea:嗯,我认为你应该停止在服务定位器上添加更多依赖项. (2认同)