2010-09-10 86 views
4

如果我有下面的代码,用IoC代替它的最佳实践/设计认证(我们正在使用Castle Windsor)。由于“using”语句负责创建连接对象,因此不能直接将其注入到构造函数或方法中。 注:使用SQL连接,这似乎是一个干净的例子,这里的主要好处是嘲讽/单元测试用IoC代替以下代码(Castle Windsor)

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概念时引发我们的问题。我最喜欢的方法将会如下修改方法,任何人都可以突出显示它的潜在问题?

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(); 
      } 
     } 
    } 
} 
+0

使用var cmd = con.CreateCommand()代替新的SqlCommand(str,cn) – jgauffin 2010-09-10 11:32:42

+0

@ M4N,谢谢用“var”更新。 @JQauffin:好主意,现在让代码示例保持不变我会按照“原样”离开,但会从我提议的IDatabase接口的任何实现者中删除责任。 – 2010-09-10 11:37:29

回答

1

我已经使用了IoC但不是Castle,尽管它们都是相似的,所以这里是我对此的看法。

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

UPDATE

他们继承/实现IDisposable所以你可以使用using语句。对不起,我错了。

+0

@Alistad,我只是看了一下接口的MSDN定义,并说这两个提到的是从IDisposable继承的。 http://msdn.microsoft.com/en-us/library/system.data.idbconnection.aspx和http://msdn.microsoft.com/en-us/library/system.data.idbcommand.aspx – 2010-09-10 11:27:34

+0

对不起,我的对象浏览器没有显示我这个,好笑... – Aliostad 2010-09-10 11:31:12

1

虽然我不会试图模拟接口IDbConnectionIDbCommand,但由于这可能很复杂,并且更重要的是不会告诉您代码是否按预期工作,所以一般方法对我来说似乎很好。

它可以让你改变你使用的数据库,所以你可以使用类似Sqlite的东西进行单元测试,然后在集成测试期间针对生产数据库测试代码。

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

+0

好主意,以清理连接字符串,我会保持原样,以保持示例代码的合理长度。使用Moq我不打算模拟整个IDbConnection或存储库,只是与测试相关的位(即超时或不可用)。 – 2010-09-10 13:35:59