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

如何为动态创建的Lambda表达式参数标记特性?

如何为表达式树生成的Lambda参数添加特性?

常规表达式树生成Lambda的方式(比如求和示例)无法直接为参数添加特性,因为Expression.Parameter()静态方法没有提供添加特性的入口。但我们可以通过Expression.MakeParameter()方法结合特性数据,实现给参数标记特性的需求,完全适配动态生成Minimal API端点这类场景。

目标效果

我们需要生成等价于以下代码的表达式树:

([FromServices] ISender sender, [FromBody] LoginDto body, CancellationToken ct) =>
    sender.Send(new LoginQuery(body), ct)

实现步骤与代码示例

  1. 构造特性的CustomAttributeData
    表达式树通过CustomAttributeData识别参数特性,我们可以直接从特性实例中获取该数据。

  2. 用Expression.MakeParameter创建带特性的参数
    替代Expression.Parameter(),使用Expression.MakeParameter()传入特性数据集合,生成带标记的参数。

  3. 构建Lambda逻辑体并编译
    按常规方式构建Lambda的执行逻辑,最后生成并编译完整的Lambda表达式。

完整代码示例:

using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc;
// 假设ISender、LoginDto、LoginQuery已提前定义

// 生成[FromServices]特性的数据
var fromServicesAttrData = CustomAttributeData.GetCustomAttributeData(new FromServicesAttribute());
// 创建带[FromServices]标记的sender参数
var senderParam = Expression.MakeParameter(
    typeof(ISender),
    "sender",
    false,
    new[] { fromServicesAttrData }
);

// 生成[FromBody]特性的数据
var fromBodyAttrData = CustomAttributeData.GetCustomAttributeData(new FromBodyAttribute());
// 创建带[FromBody]标记的body参数
var bodyParam = Expression.MakeParameter(
    typeof(LoginDto),
    "body",
    false,
    new[] { fromBodyAttrData }
);

// 创建无特性的CancellationToken参数
var ctParam = Expression.Parameter(typeof(CancellationToken), "ct");

// 构建Lambda执行体:sender.Send(new LoginQuery(body), ct)
var loginQueryInstance = Expression.New(typeof(LoginQuery).GetConstructor(new[] { typeof(LoginDto) })!, bodyParam);
var sendCall = Expression.Call(
    senderParam,
    typeof(ISender).GetMethod(nameof(ISender.Send), new[] { typeof(object), typeof(CancellationToken) })!,
    loginQueryInstance,
    ctParam
);

// 生成并编译Lambda表达式
var lambda = Expression.Lambda<Func<ISender, LoginDto, CancellationToken, Task<object>>>(
    sendCall,
    senderParam,
    bodyParam,
    ctParam
);
var func = lambda.Compile();

关键说明

  • CustomAttributeData.GetCustomAttributeData()可以直接从特性实例提取所需数据,无需手动构造CustomAttributeData,简化代码。
  • Expression.MakeParameter()的第四个参数支持传入多个CustomAttributeData实例,可为单个参数标记多个特性。
  • 用这种方式生成的Lambda参数会携带对应的特性标记,完全满足动态生成Minimal API端点的需求,能有效合并端点层与CQRS层,减少重复样板代码。

内容的提问来源于stack exchange,提问作者Massimiliano Kraus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 08:50:08