导致“扩展方法无法动态调度”的原因在这里?

时间:2013-03-13 16:33:03

标签: c# .net compiler-errors extension-methods dapper

编译错误

  

'System.Data.SqlClient.SqlConnection'没有名为'Query'的适用方法,但似乎有一个名称的扩展方法。无法动态分派扩展方法。考虑转换动态参数或调用扩展方法而不使用扩展方法语法。

现在,我知道如何解决这个问题,但我正在努力更好地理解错误本身。我正在上课,以利用Dapper。最后,我将提供一些更多自定义功能,以使我们的数据访问类型更加简化。特别是在追踪和东西建设。但是,现在它就像这样简单:

public class Connection : IDisposable
{
    private SqlConnection _connection;

    public Connection()
    {
        var connectionString = Convert.ToString(ConfigurationManager.ConnectionStrings["ConnectionString"]);
        _connection = new SqlConnection(connectionString);
        _connection.Open();
    }

    public void Dispose()
    {
        _connection.Close();
        _connection.Dispose();
    }

    public IEnumerable<dynamic> Query(string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
    {
        // this one works fine, without compile error, so I understand how to
        // workaround the error
        return Dapper.SqlMapper.Query(_connection, sql, param, transaction, buffered, commandTimeout, commandType);
    }

    public IEnumerable<T> Query<T>(string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
    {
        // this one is failing with the error
        return (IEnumerable<T>)_connection.Query(sql, param, transaction, buffered, commandTimeout, commandType);
    }
}

但有趣的是,如果我只是发表这样的声明:

_connection.Query("SELECT * FROM SomeTable");

它编译得很好。

那么,有人可以帮助我理解为什么在其他方法中利用相同的重载会导致该错误失败吗?

2 个答案:

答案 0 :(得分:39)

  

那么,有人可以帮助我理解为什么在其他方法中利用相同的重载会导致该错误失败吗?

正是因为您使用动态值(param)作为参数之一。这意味着它将使用动态调度...但扩展方法不支持动态调度。

解决方案很简单:只需直接调用静态方法:

return SqlMapper.Query(_connection, sql, param, transaction,
                       buffered, commandTimeout, commandType);

(假设您确实需要paramdynamic类型,当然......如评论中所述,您可以将其更改为object。 )

答案 1 :(得分:1)

同一问题的另一个解决方案是将类型转换应用于动态值。

我遇到了同样的编译错误:

Url.Asset( "path/" + article.logo );

通过以下方式解决了这个问题:

Url.Asset( "path/" + (string) article.logo );

注意:在这种情况下,动态值是众所周知的字符串;由存在的字符串连接加强的事实。