C#运行时动态构建属性表达式以调用泛型Patch API
解决方案
一、构建Expression<Func<T, object>>(运行时已知T和属性名)
如果编译时能确定T的类型,直接用泛型方法构建即可:
public static Expression<Func<T, object>> BuildPropertyExpr<T>(string propertyName) { // 定义参数x(类型为T) var param = Expression.Parameter(typeof(T), "x"); // 获取属性访问表达式 var propAccess = Expression.Property(param, propertyName); // 值类型需要装箱为object,引用类型直接转换不影响 var boxedExpr = Expression.Convert(propAccess, typeof(object)); // 包装成Lambda表达式 return Expression.Lambda<Func<T, object>>(boxedExpr, param); }
如果T的类型也是运行时动态确定的,可直接构建非泛型表达式再转换:
public static Expression BuildPropertyExpr(Type tType, string propertyName) { var param = Expression.Parameter(tType, "x"); var propAccess = Expression.Property(param, propertyName); var boxedExpr = Expression.Convert(propAccess, typeof(object)); return Expression.Lambda(typeof(Func<,>).MakeGenericType(tType, typeof(object)), boxedExpr, param); }
二、运行时调用Patch<T, TProperty>方法
因为Patch是泛型方法,且T和TProperty都只能在运行时确定,需通过反射结合表达式构建实现:
public static void InvokePatch(object apiInstance, Type tType, string id, string propertyName, object value) { // 1. 获取目标属性的信息 PropertyInfo propInfo = tType.GetProperty(propertyName); Type tPropType = propInfo.PropertyType; // 2. 构建字段路径表达式 x => x.PropertyName var param = Expression.Parameter(tType, "x"); var propAccess = Expression.Property(param, propInfo); var fieldPathExpr = Expression.Lambda( typeof(Func<,>).MakeGenericType(tType, tPropType), propAccess, param); // 3. 获取泛型版本的Patch方法 MethodInfo patchMethod = apiInstance.GetType() .GetMethod("Patch") .MakeGenericMethod(tType, tPropType); // 4. 调用Patch方法 patchMethod.Invoke(apiInstance, new object[] { id, fieldPathExpr, value }); }
关键说明
- 构建表达式时必须严格匹配API要求的泛型委托类型(
Func<T, TProperty>),否则API无法识别。 - 反射调用泛型方法时,需通过
MakeGenericMethod传入正确的T和TProperty类型,才能匹配到对应的方法重载。 - 全程未使用
PropertyInfo.GetValue/SetValue,完全通过表达式和反射调用API的方式满足需求。
内容的提问来源于stack exchange,提问作者Stephan Steiner
相关产品推荐
相关产品推荐

