重构两个非常相似的重载

时间:2016-06-20 19:58:59

标签: c# refactoring

我有一个超载:

White

和另一个重载:

public DataTable ExecuteStoredProcedure(string storedProcedure)
        {
            var dataTable = new DataTable();
            using (var odbcConnection = _connection)
            {
                using (var odbcCommand = odbcConnection.CreateCommand())
                {
                    odbcCommand.CommandText = storedProcedure;
                    odbcCommand.CommandType = CommandType.StoredProcedure;
                    using (var adapter = new OdbcDataAdapter(odbcCommand))
                    {
                        adapter.Fill(dataTable);
                    }
                }
            }

            return dataTable;
        }

其中的内容非常相似。事实如此相似,唯一的区别在于这一行:

    public DataTable ExecuteStoredProcedure(string storedProcedure, List<StoredProcedureParameters> storedProcedureParameters)
    {
        var dataTable = new DataTable();
        using (var odbcConnection = _connection)
        {
            using (var odbcCommand = odbcConnection.CreateCommand())
            {
                odbcCommand.CommandText = storedProcedure;

                foreach (var parameter in storedProcedureParameters)
                {
                    odbcCommand.Parameters.Add("@" + parameter.ParameterName, parameter.ParameterType, 
                        parameter.LengthOfParameter).Value = parameter.ParameterName;
                }

                odbcCommand.CommandType = CommandType.StoredProcedure;
                using (var adapter = new OdbcDataAdapter(odbcCommand))
                {
                    adapter.Fill(dataTable);
                }
            }
        }

        return dataTable;
    }

我花了几个小时试图重构这个人,因为他们非常相似。我试过代理,但它使代码更难以理解。我无法组合两个重载的功能,因为其他重载逻辑发生在另一个的中间。有没有人对如何将其重构为一种可读的方法有任何想法?

4 个答案:

答案 0 :(得分:1)

你可以做的事情很多:

您可以随时使用一种方法,但使用可选的List<StoredProcedureParameters>

像这样:(为简洁起见,我将其重命名为spParams

public DataTable ExecuteStoredProcedure(string storedProcedure,
                                        List<StoredProcedureParameters> spParams
                                                     = new List<StoredProcedureParameters>())
{
    var dataTable = new DataTable();
    using (var odbcConnection = _connection)
    {
        using (var odbcCommand = odbcConnection.CreateCommand())
        {
            odbcCommand.CommandText = storedProcedure;

            foreach (var parameter in spParams)
            {
                odbcCommand.Parameters.Add("@" + parameter.ParameterName, parameter.ParameterType, 
                    parameter.LengthOfParameter).Value = parameter.ParameterName;
            }

            odbcCommand.CommandType = CommandType.StoredProcedure;
            using (var adapter = new OdbcDataAdapter(odbcCommand))
            {
                adapter.Fill(dataTable);
            }
        }
    }

    return dataTable;
}

这样,您可以调用相同的方法,并选择是否传递List<StoredProcedureParameters>(或不传入)。

使用默认值为spParams= new List<StoredProcedureParameters>()的参数将意味着调用原始1参数签名的任何现有代码仍然有效,从而节省了额外重构的时间。

另外,这意味着您现有的foreach块只会迭代一个空列表。

您可以执行与上面类似的操作,只需将spParams值设为null作为默认设置,然后执行空检查,如下所示:

public DataTable ExecuteStoredProcedure(string storedProcedure,
                                        List<StoredProcedureParameters> spParams = null)
{
    //...

    if (spParams != null) // Check if the spParams is null
    {
        foreach(var param in spParams)
        {
            // Loop in here, if not null
        }
    }

    //...
}

希望这会有所帮助:)

答案 1 :(得分:1)

两种方法 -

  1. 您可以将第一个方法传递给第二个方法的空参数列表:

    public DataTable ExecuteStoredProcedure(string storedProcedure)
    {
        return ExecuteStoredProcedure(storedProcedure, new List<StoredProcedureParameters>());
    }
    
  2. 您可以从第一个方法传递null,并在第二个方法中添加一个空检查,如下所示:

    public DataTable ExecuteStoredProcedure(string storedProcedure)
    {
        return ExecuteStoredProcedure(storedProcedure, null);
    }
    

    ...

    if (storedProcedureParameters != null)
    {
            foreach (var parameter in storedProcedureParameters)
            {
                    odbcCommand.Parameters.Add("@" + parameter.ParameterName, parameter.ParameterType, parameter.LengthOfParameter).Value = parameter.ParameterName;
            }
    }
    

答案 2 :(得分:0)

如果要运行foreach,可以添加标记以标记。当然,有必要更改参数名称,这只是重构的一种可能变体:

public DataTable ExecuteStoredProcedure(string storedProcedure, List<StoredProcedureParameters> storedProcedureParameters, bool withForEach)
    {
        var dataTable = new DataTable();
        using (var odbcConnection = _connection)
        {
            using (var odbcCommand = odbcConnection.CreateCommand())
            {
                odbcCommand.CommandText = storedProcedure;
                if(withForEach)
                foreach (var parameter in storedProcedureParameters)
                {
                    odbcCommand.Parameters.Add("@" + parameter.ParameterName, parameter.ParameterType, 
                        parameter.LengthOfParameter).Value = parameter.ParameterName;
                }

                odbcCommand.CommandType = CommandType.StoredProcedure;
                using (var adapter = new OdbcDataAdapter(odbcCommand))
                {
                    adapter.Fill(dataTable);
                }
            }
        }

        return dataTable;
    }

答案 3 :(得分:0)

为什么你不能做这样的事......

public DataTable ExecuteStoredProcedure(string storedProcedure)
{
    return ExecuteStoredProcedure(storedProcedure, null);
}

public DataTable ExecuteStoredProcedure(string storedProcedure, List<StoredProcedureParameters> storedProcedureParameters)
{
    var dataTable = new DataTable();
    using (var odbcConnection = _connection)
    {
        using (var odbcCommand = odbcConnection.CreateCommand())
        {
            odbcCommand.CommandText = storedProcedure;

            if(storedProcedureParameters != null)
            {
                foreach (var parameter in storedProcedureParameters)
                {
                    odbcCommand.Parameters.Add("@" + parameter.ParameterName, parameter.ParameterType, 
                        parameter.LengthOfParameter).Value = parameter.ParameterName;
                }
            }

            odbcCommand.CommandType = CommandType.StoredProcedure;
            using (var adapter = new OdbcDataAdapter(odbcCommand))
            {
                adapter.Fill(dataTable);
            }
        }
    }

    return dataTable;
}