Tengo curiosidad por ver si alguien más ha tenido este mismo problema ... Estoy usando Dapper como en ORM para un proyecto y estaba creando algunos de mis propios métodos de extensión de la interfaz IDbConnection
con el fin de simplificar el código, donde me encontré con (lo que encontré) error de desconcierto.No puedo llamar a los métodos de extensión con parámetros dinámicos y genéricos
Voy a caminar a través del proceso que atravesé.
En primer lugar, he añadido un método de extensión de mi proyecto en una clase estática denominada DbExtensions
así:
using System.Collections.Generic;
using System.Data;
using System.Linq;
public static class DbExtensions
{
public static T Scalar<T>(
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
var ret = cnn.Query<T>(sql, param as object, transaction, buffered, commandTimeout, commandType).First();
return ret;
}
}
Esto crea un error de compilación con la siguiente descripción:
'System.Data.IDbConnection' has no applicable method named 'Query' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
Esto está bien, y el error es bastante útil, ya que incluso me dice cómo solucionarlo. Por lo tanto, a continuación, tratar:
using System.Collections.Generic;
using System.Data;
using System.Linq;
public static class DbExtensions
{
public static T Scalar<T>(
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
var ret = SqlMapper.Query<T>(cnn, sql, param, transaction, buffered, commandTimeout, commandType).First();
return ret;
}
}
y compila correctamente. Algo extraño está sucediendo sin embargo. En Visual Studio, si tomo el valor devuelto de SqlMapper.Query<T>
que debe ser IEnumerable<T>
, y trato de operar en él, Visual Studio no me otorga NINGUNA propiedad intellisense excepto las heredadas a través de object
.
Pensando que estoy haciendo algo que intellisense no es lo suficientemente inteligente como para descubrirlo, sigo mi camino feliz ... hasta que intento ejecutar el código.
Cuando trato de ejecutarlo, se dispara hasta donde yo estoy llamando .First()
con el siguiente error:
'System.Collections.Generic.List<MyNameSpace.MyClass>' does not contain a definition for 'First'
Ahora este error, pensé que era interesante ... Después de golpearse la cabeza durante una Mientras, me di cuenta de que el primer argumento se quejaba del tipado dinámico ...
Supongo que este error ocurre porque el compilador no puede construir la Plantilla genérica porque no sabe que Query está devolviendo IEnumerable<T>
mientras se está ejecutando en el DLR? Me encantaría escuchar a alguien explicar esto, que estaba bien informado. He encontrado básicamente dos maneras de solucionarlo:
- emitir el parámetro
dynamic
a unobject
- Fundido el valor devuelto a una
IEnumerable<T>
using System.Collections.Generic;
using System.Data;
using System.Linq;
public static class DbExtensions
{
public static T Scalar<T>(
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
var ret = SqlMapper.Query<T>(cnn, sql, param as object, transaction, buffered, commandTimeout, commandType).First();
return ret;
}
}
using System.Collections.Generic;
using System.Data;
using System.Linq;
public static class DbExtensions
{
public static T Scalar2<T>(
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
var ret = ((IEnumerable<T>)SqlMapper.Query<T>(cnn, sql, param, transaction, commandTimeout, commandType)).First();
return ret;
}
}
EN RESUMEN:
Soy nuevo en el trabajo a través de los qwerks del DLR y parece haber algunas advertencias a tener en cuenta cuando se juega con Dynamic + Generics ...?
Sé que esto no es una pregunta per se, pero cuando realmente empecé a escribir esto, no sabía lo que estaba pasando y lo he descubierto en el proceso! Pensé que podría ayudar a alguien con problemas similares aunque ...
posible duplicado de [Método de extensión y objeto dinámico en C#] (http://stackoverflow.com/questions/5311465/extens ión-método-y-dinámico-objeto-en-do sostenido) –
Esto es impresionante, pero tenga en cuenta que para las preguntas de auto-respondido a la Convención es lo ideal para publicar la pregunta y la respuesta por separado. – McGarnagle
@dbaseman Gracias. Me escribió una respuesta por separado, pero al parecer no tengo suficientes puntos para "auto-respuesta" hasta que hayan transcurrido 8 horas: P –