在我的应用程序中,我使用Dapper访问数据库。
我有以下示例代码:
public IEnumerable GetByParentId(Type childType, string table)
{
IDbConnection _connection = _dbProvider.GetConnection();
var _sqlString = "select * from " + table;
IEnumerable _ret = _connection.Query(_sqlString).ToList();
//return IEnumerable<Dapper.SqlMapper.FastExpando>
return _ret;
}
可以将FastExpando
项投射到我的childType
或强制Dapper返回强类型集合吗?
我无法更改我的方法签名!
答案 0 :(得分:3)
您可以通过反射调用Query方法并提供childType的通用TItem参数。然后,Dapper将返回IEnumerable,你将能够投射它。 此外,您可以派Dapper(它不是很大)并进行一个非常简单的Query重载,它将包含(Type childType)参数并在其中调用正确的方法。
您所面临的是使用泛型时C#的问题。作为静态类型语言,C#在处理动态类型时很糟糕。如果你想动态工作,你总会得到反思。
以下是如何使用类型参数调用查询方法的示例。您可能需要纠正一下:
public IEnumerable GetByParentId(Type childType, string table)
{
IDbConnection _connection = _dbProvider.GetConnection();
var _sqlString = "select * from " + table;
var t = typeof(SqlMapper);
var genericQuery = t.GetMethods().Where(x => x.Name == "Query" && x.GetGenericArguments().Length == 1).First(); // You can cache this object.
var concreteQuery = genericQuery.MakeGenericMethod(childType); // you can also keep a dictionary of these, for speed.
var _ret = (IEnumerable)concreteQuery.Invoke(null, new object[] { _connection, _sqlString });
return _ret;
}
附加:
另外,我在这里看到了更普遍的设计问题。你想动态指定类型,但是想要获得静态类型的对象,你将能够投射(我假设是静态的,或者你想继续反射?)。然后......为什么你首先创建动态界面?你说,你不能改变界面,但这看起来有点愚蠢。似乎所有上下文都是静态类型的,但是,出于某种原因,你有一个动态类型的方法。 如果您在编译期间(或通过运行时中的泛型参数)知道类型,那么您应该简单地将方法更改为:
public IEnumerable<T> GetByParentId<T>(string table)
{
IDbConnection _connection = _dbProvider.GetConnection();
var _sqlString = "select * from " + table;
var _ret = _connection.Query<T>(_sqlString);
return _ret;
}