C#中如何将字符串转为实体属性表达式供Projection.Include使用
问题描述
我正在按如下方式创建投影变量:
var projection = Builders<Items>.Projection .Include(x => x.Name);
Include方法的入参为Expression<Func<TSource,object>> field类型的表达式。
我希望将名为key的字符串参数(例如取值为"Name")转换为x.Name形式的属性访问表达式,从而能够在运行时动态投影Items类型的其他字段,期望实现的调用逻辑如下:
var key = "Name"; var projection = Builders<Items>.Projection .Include(x => x."key");
解决方案
你可以选择以下两种实现方式:
方式1:手动构造表达式树(完全匹配强类型Lambda的传参形式)
使用.NET内置的表达式树API动态生成目标Lambda即可,无需依赖第三方包,可以封装成通用扩展方法方便调用:
using System.Linq.Expressions; using MongoDB.Driver; public static class ProjectionBuilderExtensions { public static ProjectionDefinition<T> IncludeDynamic<T>( this ProjectionDefinitionBuilder<T> projectionBuilder, string propertyName) { // 构造Lambda表达式的参数:对应 x => 里的x var parameterExpr = Expression.Parameter(typeof(T), "x"); // 构造属性/字段访问表达式:对应 x.Name 这类成员访问逻辑 var memberAccessExpr = Expression.PropertyOrField(parameterExpr, propertyName); Expression lambdaBody = memberAccessExpr; // 当属性是值类型时,需要做装箱转换,才能匹配Expression<Func<T, object>>的返回值签名 if (memberAccessExpr.Type.IsValueType) { lambdaBody = Expression.Convert(memberAccessExpr, typeof(object)); } // 组装成完整的Lambda表达式 var includeLambda = Expression.Lambda<Func<T, object>>(lambdaBody, parameterExpr); return projectionBuilder.Include(includeLambda); } }
调用方式和预期逻辑一致:
var key = "Name"; var projection = Builders<Items>.Projection.IncludeDynamic(key);
方式2:直接使用驱动原生的字符串传参(代码更简洁)
实际上Include方法接收的FieldDefinition<TSource>类型本身就支持从字符串隐式转换,绝大多数场景下你根本不需要手动构造表达式树,直接传入字符串类型的字段名即可正常工作:
var key = "Name"; // 直接传字符串字段名,驱动内部会自动处理字段映射 var projection = Builders<Items>.Projection.Include(key);
提示:如果你的实体属性通过
[BsonElement("xxx")]特性配置了和属性名不同的MongoDB存储字段名,直接传入实际存储的Bson字段名即可生效。
内容的提问来源于stack exchange,提问作者LightTechnician
相关产品推荐
相关产品推荐

