我有以下情况。某些.Net运行时方法不能很好地工作,我需要制定一种解决方法。就像SqlCommand.ExecuteReader()有时返回一个封闭的阅读器对象,我想要这样的代码:

 SqlDataReader MyExecuteReader( this SqlCommand command )
 {
     var reader = command.ExecuteReader();
     if( reader.IsClosed() ) {
        throw new ClosedReaderReturnedException();
     }
     return reader;
 }

一切都很好,除非我现在需要更改所有调用ExecuteReader()的代码,以便现在可以调用MyExecuteReader()并使维护更加困难。

有没有办法声明我的任何代码何时要调用称为SqlCommand.ExecuteReader()MyExecuteReader()?有效地可以用另一种具有完全相同的签名和相同名称的方法替换现有方法吗?

最佳答案

这类似于尝试使用模拟对单元代码进行测试时的问题。

解决该问题的一种方法是,使用实现SqlCommand方法的接口(interface)的对象替换代码中对ExecuteReader的使用。然后,您可以使用工厂模式更轻松地替换对象。

因此,您将替换如下代码:

using (SqlCommand command = new SqlCommand(query))
{
    command.ExecuteReader();
}

和:
var sqlCommandFactory = new SqlCommandFactory();
using (ISqlCommand command = sqlCommandFactory.CreateSqlCommand(query))
{
    command.ExecuteReader();
}

首先定义一个接口(interface),其中包含要替换的方法:
public interface ISqlCommand
{
    SqlDataReader ExecuteReader();

    // further interface methods here...
}

然后创建一个工厂,该工厂使用与SqlCommand构造函数相同的签名:
internal class SqlCommandFactory
{
    bool _useMyClass = true;

    public ISqlCommand CreateSqlCommand(string query)
    {
        if (_useMyClass)
        {
            return new MySqlCommand(query);
        }
        else
        {
            return new SqlCommandWrapper(query);
        }
    }
}

然后,您在MySqlCommand类中编写替代代码:
public MySqlCommand : ISqlCommand
{
    public SqlDataReader ExecuteReader()
    {
        // your new code here
    }
}

由于.NET SqlCommand类显然未实现新的ISqlCommand接口(interface),因此创建一个包装类来执行此操作:
public SqlCommandWrapper : ISqlCommand
{
    SqlCommand _sqlCommand;

    public SqlCommandWrapper(string query)
    {
        _sqlCommand = new SqlCommand(query);
    }

    public SqlDataReader ExecuteReader()
    {
        _sqlCommand.ExecuteReader();
    }
}

要做一些额外的工作,但是此方法的好处是您可以将实现更改为所需的任何内容,包括进行单元测试(通过将模拟工厂传递给代码)。

额外的工作应该是一次性的,并按要求保留名称和原始方法签名。与自定义/扩展方法相比,这应该使您的代码看起来更加熟悉和易于理解(尤其是在您(或您的团队)习惯了这种众所周知的模式之后)。

关于c# - 我可以将C#方法替换为具有相同名称和签名的另一个方法吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14229444/

10-17 02:18