数据访问层的静态方法与依赖注入

cae*_*rdo 7 c# asp.net-mvc dependency-injection inversion-of-control

对于我的 ASP.NET MVC 项目,我曾经严重依赖静态方法来访问我的数据,有点像这样:

public class MyTable
{

    public static IEnumerable<MyTable> findAll()
    {
        using (var connection = new SqlConnection(Provider.connString))
        {
            //implementation here
        }


        return datas;
    }

    public static MyTable find(guid id)
    {
        using (var connection = new SqlConnection(Provider.connString))
        {
            //implementation here
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

所以我可以在我的控制器中这样称呼它们:

var datas = MyTable.findAll();
Run Code Online (Sandbox Code Playgroud)

我对它很满意,但我怀疑我在使用它进行数据访问方面做得很好。

现在,我正在尝试将依赖注入仅用于某些学习目的到我的数据访问类中,如下所示:

public class MyTable
{

    public IDatabaseEngine _engine = null;

    public MyTable()
    {
    }

    public MyTable(IDatabaseEngine engine)
    {
        _engine = engine;
    }

    public IEnumerable<MyTable> findAll()
    {
        using (var connection = _engine.getConnection())
        {
            //implementation here
        }
        return datas;
    }

    public MyTable find(guid id)
    {
        using (var connection = _engine.getConnection())
        {
            //implementation here
        }
        return data;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,这意味着我必须创建一个MyTable类的实例来调用我的控制器上的数据访问方法,如下所示:

var table = new MyTable(new MSSQLEngine(provider.connString));
var datas = table.findAll(); 
Run Code Online (Sandbox Code Playgroud)

好吧,要么我没有经验解决这个问题,要么我做错了,我觉得为我需要的每个数据访问实例化对象感到不舒服。

我的问题是

  1. 我做依赖注入错了吗?(我觉得我是)
  2. 创建数据访问类的对象以在控制器或其他类中调用数据访问方法是一种好习惯吗?
  3. 使用静态方法来代替它是一种好习惯吗?(就像我在第一个例子中所做的那样)
  4. 如果我的 DI 实现是错误的,我该如何使它正确?

mag*_*nes 5

虽然 DI 在某些情况下很酷,但在大多数情况下是过度工程!

我解释。如何创建静态方法。只需将“静态”放在方法前面。您可以通过调用 Class.Method() 轻松调用它。此外,它对系统很有效,因为该方法只创建一次。

优点:高效。缺点:不可变

在 DI 时,您可能需要一些容器,然后是一个接口,您可以添加一个类,任何实现该接口的类。并且,在代码的某些部分,您将需要创建类的实例(也就是方法的新实例)。

优点:是可变的缺点:效率不高,冗长。


And*_*iuc 3

对您问题的答复:

  1. 不是,请看下面详细解答
  2. DI 的主要优点是依赖于抽象而不是实现。您不需要创建类的实例,DI 会为您完成。您只需将接口注入到您的类中并在 IoC 中注册它们。
  3. 不,因为您将无法为您的方法编写单元测试。
  4. 见下文。

要正确使用 DI,首先需要将MyTable类提取到接口中,然后将该接口注入到控制器中。

public interface IMyTable 
{
    IEnumerable<MyTable> findAll();
    // other methods
}

public class MyTable : IMyTable 
{
    // your implementation
}
Run Code Online (Sandbox Code Playgroud)

那么你的控制器应该是这样的:

public class YourController : Controller
{ 
    private IMyTable myTable;
    public YourController(IMyTable myTable)
    {
        this.myTable = myTable;
    }

    public ActionResult YourAction()
    {
        var result = myTable.findAll();
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我个人使用 Castle Windsor 作为 IoC 容器,下面是在 ASP.NET MVC 应用程序中使用 Castle Windsor 的示例