【问题标题】:Replacing following code with IoC (Castle Windsor)用 IoC (Castle Windsor) 替换以下代码
【发布时间】:2010-09-10 10:58:05
【问题描述】:

如果我有下面的代码,用 IoC 替换它的最佳实践/设计考虑是什么(我们希望使用 Castle Windsor)。由于“using”语句负责创建连接对象,因此您不能将其直接注入构造函数或方法中。 注意:使用 SQL 连接作为一个干净的示例,这里的主要好处是模拟/单元测试

public void CustomerRespository
{
    ....
    public void Save(Customer customer)
    {
       using (var cn = new SqlConnection(connectionString))
       {
           using (var cm = new SqlCommand(commandString, cn))
           {
              ....
              cn.Open();
              cm.ExecuteNonQuery();
           }
       }
    }
}

我相信至少会有一些选择,但由于我们刚刚开始使用 IoC,我不确定它们以后不会给我们带来问题和/或面对 IoC 概念。我最喜欢的方法是修改方法如下,任何人都可以强调它的潜在问题吗?

public interface IDatabase
{
    IDbConnection Connection(string connectionString);
    IDbCommand Command(string text, IDbConnection conn);
}

public class SqlDB : IDatabase
{
    IDbConnection Connection(string connectionString)
    { return new SqlConnection(connectionString); }

    IDbCommand Command(string text, IDbConnection conn)
    { return new SqlCommand(text, conn); }
}

public interface ICustomerRespository
{
   void Save(Customer customer)
}

public class CustomerRespository : ICustomerRespository
{
    public IDatabase DB{get; private set;}

    public CustomerRespository( IDatabase db)
    {
       DB = db;
    }

    ....
    public void Save(Customer customer)
    {
       using (var cn = DB.Connection(connectionString))
       {
           using (var cm = DB.Command(commandString, cn))
           {
              ....
              cn.Open();
              cm.ExecuteNonQuery();
           }
       }
    }
}

【问题讨论】:

  • 使用 var cmd = con.CreateCommand() 而不是 new SqlCommand(str, cn)
  • @M4N,感谢更新了“var”。 @JQauffin:好主意,现在为了保持代码示例相同,我将“按原样”保留,但会从我提议的 IDatabase 接口的任何实现者那里移除责任。

标签: c# castle-windsor ioc-container


【解决方案1】:

我使用过 IoC,但没有使用 Castle,尽管它们都很相似,所以这是我的收获。

我认为您走在正确的轨道上 - 尽管我可能会使用单独的工厂进行连接和命令,或者实际上将连接打开和命令运行到另一个类,因此存储库不必知道这个细节。只需在您的类的构造函数中使用 IDatabase 以便注入它(或者如果您使用基于属性的注入,则使用属性)。将代码中的 SqlConnection 和 SqlCommand 替换为 IDbConnection 和 IDbCommand。

更新

它们确实继承/实现了 IDisposable,因此您可以使用 using 语句。对不起我的错误。

【讨论】:

【解决方案2】:

一般方法对我来说似乎很好,尽管我不会尝试模拟 IDbConnectionIDbCommand 接口,因为这可能很复杂,更重要的是不会告诉您代码是否按预期工作。

但是,它允许您更改您使用的数据库,因此您可以使用 Sqlite 之类的东西进行单元测试,然后在集成测试期间针对您的生产数据库测试代码。

您还可以将连接字符串移动到 IDatabase 抽象中,这将简化客户端。

【讨论】:

  • 整理连接字符串的好主意,我有点保留示例代码的合理长度。使用 Moq,我不会想模拟整个 IDbConnection 或存储库,只模拟与测试相关的位(即超时或不可用)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-02
  • 1970-01-01
  • 2013-08-21
  • 2011-04-05
相关资源
最近更新 更多