用非静态类包装静态类

时间:2013-12-30 21:51:05

标签: c# oop static-classes

我正在看一个项目,我发现了一些非常好奇的东西。

有一个静态类,它有一组方法,每个方法都调用一个远程服务器。

模板看起来像这样:

public static class DAI

    public static ResponseObject ExecStatement(string db, string sql)
    {
         { ... }
    }

    public static DataSetResponseObject GetDataSet(string db, string sql)
    {
         { ... }
    }

    public static DataTableResponseObject GetDataTable(string db, string sql)
    {
         { ... }
    }
}

但项目中没有地方调用此类。相反,它会调用非静态类容器。

public class ExecSP : IExecSP
{
    string _db;
    public ExecSP(string db)
    {
        _db = db;
    }

    public ResponseObject OutputAsResponseObject(string sql)
    {
         return DAI.ExecStatement(_db, sql);
    }

    public ResponseObject OutputAsDataSet(string sql)
    {
         return DAI.GetDataSet(_db, sql);
    }

    public ResponseObject OutputAsDataTable(string sql)
    {
         return DAI.GetDataTable(_db, sql);
    }
}

现在,我认为只有两个优点是,当包装在一个非静态容器中时,命名法更加清晰,并且传递的参数较少。

但我想知道设计用非静态包装静态类是否是一个好主意?如果有的话还有什么其他原因?因为我认为创建一个静态并调用它会没问题。但是这个项目已经成为一个包含所有静态类的故意点。而且我不确定为什么。

5 个答案:

答案 0 :(得分:5)

我过去做过这样的事情的最常见的原因是静态方法是由第三方库提供的(即我没有写它),但我不想写代码直接依赖于该库。在这种情况下,我会编写自己的类,并将其视为直接依赖。

假设我使用了一个接口(或类似于你的例子),那么如果我决定使用不同的库,我可以编写另一个实现相同接口的类并交换具体的类在运行时(使用依赖注入之类的东西)。

答案 1 :(得分:1)

在我看来,他们正在尝试使对象可注入,以便让您的代码更容易测试和以后修改。

查看此帖子:Why does one use dependency injection?

答案 2 :(得分:0)

就我个人而言,我永远不会这样做,我会做的是使用像Ninject或Unity这样的.NET依赖注入框架,以便在创建对象时为对象注入必要的引用。这样做有很多好处......对于初学者来说,你可以创建你的单例对象,而不必使用静态成员,你可以更好地控制它们的生命周期。如果你想进行单元测试(并且你应该)那么用一个模拟对象替换你的单例是微不足道的,如果你以后再决定一个单例不是最好的设计选择,那么注入一个对象是微不足道的限定为其他东西,例如主要的父视图模型等。您正在查看的项目可能正在使用该中间类来启用我正在谈论的一些事情,但它永远不会像以前那样灵活或干净。做适当的依赖注入。

答案 3 :(得分:0)

这是标准模式。 -包装一组更复杂的方法以隐藏其复杂性,例如一组仅通过抛出的异常返回错误的方法。 -在包装方法中处理错误,异常等 -将方法设为静态,以防止派生方法(例如executeQueryByInt,executeQueryByLong,executeQueryByString,...)相乘 -将对SQL处理框架代码的引用传播限制为仅包装的方法 -重要在一个地方可以记录使用第三方静态库时的调用方式,错误,特殊情况和错误解决方法

对于单元测试,您的单元测试应实现一个简短的包装类,该包装类仅通过对静态类的调用传递。

无论多么简单,都无需增加另一层复杂度即可适应任意模式或使您的代码模糊。您的生产代码不应实施额外的代码,即使该代码已在单元测试中使用。

通常将库或nuget程序包本身包装在一个项目中,这样一个多解决方案的项目就不会包含对第三方程序包的数十个程序包引用。

奇怪的是Angular有桶的概念,但是.net核心却没有。一旦项目数量超过10个且解决方案超过2年,您就会进入Nuget Package h * ll。

具有多次重组的1,000,000+行.net解决方案,静态方法和静态类使代码在较大的上下文中更容易移动。在较小的项目中,最佳实践可以很好地扩展,而对于超过一百万个生产线系统,则不能很好地扩展。这与玩具项目和简短博客文章中发现的方法不同。这是关于能够看到什么代码被调用以及代码在哪里被调用,以便重构,简化变得更加容易。

答案 4 :(得分:-1)

添加的课程ExecSP没有任何好处。两种方法都传入db字符串和sql字符串。我想db字符串是某种到数据库实例的连接字符串,而sql是该实例要执行的原始sql字符串。在这种情况下,也可以直接调用DAI,没有理由使用包装类。

从设计主义来看,这是紧密耦合。我们可能希望通过创建一个实例然后针对抽象运行命令而不是传递连接字符串/ sql语句来删除数据库(IDatabase)。

Psudeo代码:

IDatabase dbInstance =  new DatabaseCreator(db);
dbInstance.Execute(sql); 

然后,无论数据库是SQL Server,Oracle等都无关紧要

抽象有助于测试。例如,在单元测试项目中,我可以编写自己的IDatabase实现,甚至不使用数据库。我不确定如何在没有实际数据库实例的情况下测试它。如果我编写自己的测试实例,我可以删除该外部依赖项。