You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 08:06:50