Blazor泛型API返回T列表:如何传递共享项目类型?
解决方案
1. 核心思路:利用泛型参数自带的类型信息
你不需要额外传递字符串或手动用反射传递类型——客户端调用时指定的泛型参数T(比如List<person>)会自动传递到API的泛型方法中,直接通过typeof(T)就能获取当前的T类型。
2. 客户端泛型Post方法实现(共享项目)
先在共享项目中定义HttpClient的泛型扩展方法,方便Blazor客户端调用:
public static class HttpClientExtensions { public static async Task<T> Post<T>(this HttpClient httpClient, string requestUri, object content) { var response = await httpClient.PostAsJsonAsync(requestUri, content); response.EnsureSuccessStatusCode(); // 处理请求失败的情况 return await response.ReadFromJsonAsync<T>(); } }
客户端调用方式和你期望的一致:
List<GSPparam> parameters = new List<GSPparam>(); // 填充参数... List<person> ret = await this._http.Post<List<person>>("api/your-endpoint", parameters);
3. API端泛型方法实现
在API的控制器中,直接通过typeof(T)获取目标类型,再完成存储过程调用和类型转换:
[HttpPost] [Route("your-endpoint")] public async Task<IActionResult> ExecProcTable<T>([FromBody] List<GSPparam> parameters) { // 获取当前泛型参数T的类型(此处为List<person>) Type targetType = typeof(T); // 确认T是泛型列表类型(根据你的业务场景,也可扩展支持其他类型) if (!targetType.IsGenericType || targetType.GetGenericTypeDefinition() != typeof(List<>)) { return BadRequest("仅支持List<T>类型的返回值"); } // 获取列表的元素类型(此处为person) Type elementType = targetType.GetGenericArguments()[0]; // 1. 调用存储过程获取数据(示例:返回DataTable) DataTable procResult = await ExecuteStoredProcedure(parameters); // 2. 将DataTable转换为目标泛型列表T T result = ConvertDataTableToGenericList<T>(procResult, elementType); return Ok(result); } // 辅助方法:执行存储过程并返回DataTable private async Task<DataTable> ExecuteStoredProcedure(List<GSPparam> parameters) { // 此处编写你的存储过程调用逻辑,比如用SqlConnection、SqlCommand执行 DataTable dt = new DataTable(); // ... 执行存储过程,填充dt ... return dt; } // 辅助方法:将DataTable转换为指定泛型列表 private T ConvertDataTableToGenericList<T>(DataTable dt, Type elementType) { // 创建泛型列表实例 var list = Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)) as IList; foreach (DataRow row in dt.Rows) { // 创建元素实例 var item = Activator.CreateInstance(elementType); // 映射DataRow的列到实体属性 foreach (DataColumn col in dt.Columns) { PropertyInfo prop = elementType.GetProperty(col.ColumnName); if (prop != null && row[col] != DBNull.Value) { prop.SetValue(item, Convert.ChangeType(row[col], prop.PropertyType)); } } list.Add(item); } return (T)list; }
4. 关键注意事项
- 确保共享项目中的实体类(如
person、GSPparam)在客户端和API端都能访问,序列化/反序列化时属性名称要匹配(可使用[JsonPropertyName]特性手动映射)。 - 如果使用Entity Framework Core或ORM框架,可替换
ConvertDataTableToGenericList方法为更高效的实体映射方式(比如AutoMapper)。 - 泛型方法在ASP.NET Core Web API中完全支持,路由不会受泛型参数影响,因为路由仅依赖URL路径。
内容的提问来源于stack exchange,提问作者Dorian
相关产品推荐
相关产品推荐

