如何在未知属性类型时无分支创建NHibernate泛型Lambda表达式?
动态创建泛型Lambda表达式(Func<User, T>)用于NHibernate UpdateBuilder.Set
我需要根据属性信息动态创建泛型Lambda表达式。目前通过反射获取了User类的Counter属性,能构建表达式参数和属性表达式,但生成的是固定的Func<User, object>类型,实际需要根据属性的真实类型(如int、string、bool等)创建对应的Func<User, T>,并传入NHibernate的UpdateBuilder.Set方法来更新数据库字段。
请问有没有办法在未知属性类型的情况下,不用针对每种属性类型写分支判断代码,就能创建出对应的泛型Lambda表达式?
可以通过表达式树结合反射动态调用泛型方法实现,完全不需要写类型分支判断。核心思路是先构建属性访问的表达式主体,再动态生成对应类型的Func<TSource, TProperty>委托。
实现步骤与代码示例
// 1. 通过反射获取目标属性(示例为User类的Counter属性) PropertyInfo propertyInfo = typeof(User).GetProperty("Counter"); // 2. 构建表达式基础节点 ParameterExpression param = Expression.Parameter(typeof(User), "x"); // 对应Lambda的输入参数x MemberExpression propertyAccess = Expression.Property(param, propertyInfo); // 对应x.Counter的表达式 // 3. 动态获取并调用Expression.Lambda的泛型版本 MethodInfo lambdaGenericMethod = typeof(Expression).GetMethods() .First(m => m.Name == "Lambda" && m.ContainsGenericParameters && m.GetParameters().Length == 2) .MakeGenericMethod(typeof(Func<,>).MakeGenericType(typeof(User), propertyInfo.PropertyType)); // 4. 创建并编译泛型Lambda表达式 Delegate propertyFunc = lambdaGenericMethod.Invoke(null, new object[] { propertyAccess, new[] { param } }); // 5. 直接传入NHibernate的UpdateBuilder.Set方法 updateBuilder.Set((dynamic)propertyFunc, newValue);
关键说明
- 这段代码会自动根据属性的真实类型(如int、string)生成对应的
Func<User, T>委托,无需手动判断类型分支。 - 如果需要复用逻辑,可以封装成通用方法:
public static Delegate CreatePropertyAccessor<TSource>(PropertyInfo propertyInfo) { ParameterExpression param = Expression.Parameter(typeof(TSource), "x"); MemberExpression propertyAccess = Expression.Property(param, propertyInfo); MethodInfo lambdaMethod = typeof(Expression).GetMethods() .First(m => m.Name == "Lambda" && m.ContainsGenericParameters && m.GetParameters().Length == 2) .MakeGenericMethod(typeof(Func<,>).MakeGenericType(typeof(TSource), propertyInfo.PropertyType)); return lambdaMethod.Invoke(null, new object[] { propertyAccess, new[] { param } }); } - 利用
dynamic关键字可以直接将生成的委托传入UpdateBuilder.Set,NHibernate会自动处理类型匹配。
内容的提问来源于stack exchange,提问作者user3132295
相关产品推荐
相关产品推荐

