如何基于运行时Type调用Dapper的QueryAsync返回对应泛型集合?
可行,两种实现方案
方案1:反射调用泛型版QueryAsync<T>
直接通过反射构建并调用Dapper的泛型QueryAsync<T>方法,能直接返回IEnumerable<reportType>类型的结果,避免先拿到IEnumerable<object>再转换:
foreach(Type reportType in myReports) { using var con = new NpgsqlConnection(_configuration.GetConnectionString("...")); // 获取QueryAsync<T>的泛型方法定义 var queryGenericMethod = typeof(SqlMapper) .GetMethods(BindingFlags.Public | BindingFlags.Static) .First(m => m.Name == "QueryAsync" && m.IsGenericMethodDefinition && m.GetParameters().Length >= 3 && m.GetParameters()[0].ParameterType == typeof(IDbConnection) && m.GetParameters()[1].ParameterType == typeof(string) ) .MakeGenericMethod(reportType); // 调用异步方法,传入连接、SQL语句,参数设为null(可根据实际需求调整) var queryTask = (Task)queryGenericMethod.Invoke(null, new object[] { con, ".. query ..", null, null, null }); await queryTask; // 获取强类型结果 var typedRows = queryTask.GetType().GetProperty("Result").GetValue(queryTask); // typedRows 即为 IEnumerable<reportType> 类型 }
方案2:将IEnumerable<object>转换为目标类型枚举
如果已经用接受Type参数的重载拿到了IEnumerable<object>,可以通过反射调用Enumerable.Cast<T>将其转换为强类型枚举:
foreach(Type reportType in myReports) { using var con = new NpgsqlConnection(_configuration.GetConnectionString("...")); var rows = await con.QueryAsync(reportType , ".. query .."); // 反射调用Enumerable.Cast<T> var castMethod = typeof(Enumerable) .GetMethod("Cast") .MakeGenericMethod(reportType); var typedRows = castMethod.Invoke(null, new object[] { rows }); // typedRows 即为 IEnumerable<reportType> 类型 }
注意事项
- 反射获取方法时要精准匹配重载,Dapper有多个
QueryAsync方法,需根据参数数量和类型筛选; - 拿到强类型结果后,由于
reportType是运行时动态获取的,后续操作可能仍需借助反射或dynamic类型; - 方案1性能略优,因为Dapper会直接将查询结果映射为目标类型,无需二次转换。
内容的提问来源于stack exchange,提问作者Bruno Henri
相关产品推荐
相关产品推荐

