¿Qué causa "los métodos de extensión no se pueden distribuir dinámicamente" aquí?

.net c# compiler-errors dapper extension-methods

Pregunta

Error de compilación

'System.Data.SqlClient.SqlConnection' no tiene un método aplicable llamado 'Query' pero parece tener un método de extensión con ese nombre. Los métodos de extensión no se pueden distribuir dinámicamente. Considere enviar los argumentos dinámicos o llamar al método de extensión sin la sintaxis del método de extensión.

Ahora sé cómo solucionar el problema, pero trato de comprender mejor el error en sí. Tengo clases que estoy construyendo para apalancar a Dapper. Al final, proporcionaré algunas funcionalidades más personalizadas para hacer que nuestro tipo de acceso a los datos sea mucho más eficiente. En particular, construir en el rastreo y esas cosas. Sin embargo, en este momento es tan simple como esto:

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);
    }
}

pero, curiosamente, si tuviera que simplemente emitir una declaración como esta:

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

compila muy bien.

Entonces, ¿puede alguien ayudarme a entender por qué está apagándose la misma sobrecarga dentro de esos otros métodos con ese error?

Respuesta aceptada

Entonces, ¿puede alguien ayudarme a entender por qué está apagándose la misma sobrecarga dentro de esos otros métodos con ese error?

Precisamente porque está utilizando un valor dinámico ( param ) como uno de los argumentos. Eso significa que usará despacho dinámico ... pero el envío dinámico no es compatible con los métodos de extensión.

La solución es simple: simplemente llame directamente al método estático:

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

(Eso es suponiendo que realmente necesita que param sea ​​de tipo dynamic , por supuesto ... como se señala en los comentarios, puede estar bien simplemente cambiarlo a un object ).


Respuesta popular

Otra solución para el mismo problema es aplicar el tipo de conversión al valor dinámico.

Encontré el mismo error de compilación con:

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

Que se resolvió haciendo:

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

Nota: el valor dinámico es bien conocido por ser una cadena, en este caso; un hecho reforzado por la concatenación de cuerdas que está presente.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué