Что означает, что "методы расширения не могут быть динамически отправлены" здесь?

Ошибка компиляции

'System.Data.SqlClient.SqlConnection' не имеет применимого метода с именем "Запрос", но по этому имени имеет метод расширения. Методы расширения не могут динамически отправляться. Подумайте о том, как использовать динамические аргументы или вызывать метод расширения без синтаксиса метода расширения.

Теперь я знаю, как обойти эту проблему, но я пытаюсь лучше понять эту ошибку. У меня есть класс, который я создаю, чтобы использовать 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");

он просто компилируется.

Итак, может кто-нибудь, пожалуйста, помогите мне понять, почему использование такой же перегрузки внутри этих других методов терпит неудачу с этой ошибкой?

Ответ 1

Итак, может кто-нибудь, пожалуйста, помогите мне понять, почему использование такой же перегрузки внутри этих других методов терпит неудачу с этой ошибкой?

Именно потому, что вы используете динамическое значение (param) как один из аргументов. Это означает, что он будет использовать динамическую отправку... но динамическая отправка не поддерживается для методов расширения.

Решение просто: просто вызовите статический метод напрямую:

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

(Предполагая, что вам действительно нужно param быть типа dynamic, конечно... как отмечено в комментариях, вы вполне можете просто изменить его на object.)

Ответ 2

Другим решением той же проблемы является применение литья типа к динамическому значению.

Я столкнулся с той же ошибкой компиляции:

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

Что было разрешено:

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

Примечание: динамическое значение хорошо известно как строка, в данном случае; факт, подкрепленный конкатенацией строк, которая присутствует.