动态MemberExpression

我想创建一个只知道字段名称的MemberExpression; 例如:

public static Expression<Func> GenerateMemberExpression(string fieldName) { PropertyInfo fieldPropertyInfo; fieldPropertyInfo = typeof(TModel).GetProperty(fieldName); var entityParam = Expression.Parameter(typeof(TModel), "e"); // {e} var columnExpr = Expression.MakeMemberAccess(entityParam, fieldPropertyInfo); // {e.fieldName} var lambda = Expression.Lambda(columnExpr, entityParam) as Expression<Func>; // {e => e.column} return lambda; } 

上述问题是字段类型必须是强类型的。 将“对象”作为字段类型传递不起作用。 有没有办法生成这个? 甚至动态LINQ似乎也不起作用。

您的代码存在许多问题:

  1. 您的方法的参数称为fieldName ,但您将获得一个属性
  2. 您正在使用非genericsExpression.Lambda方法生成表达式,如果传递给方法的类型参数T与property-type不同,则可能会选择不适当的委托类型。 在这种情况下,从表达式到方法的返回类型的as cast将失败并计算为null 。 解决方案:将通用 Lambda方法与适当的类型参数一起使用。 不需要铸造。
  3. 如果你解决了第二个问题,当从属性类型到T的安全引用转换可用时,事情将正常工作,但是当需要更复杂的转换(例如装箱/提升)时则不行。 解决方案:必要时使用Expression.Convert方法。

以下是针对这些问题的示例更新:

 public static Expression> GenerateMemberExpression (string propertyName) { var propertyInfo = typeof(TModel).GetProperty(propertyName); var entityParam = Expression.Parameter(typeof(TModel), "e"); Expression columnExpr = Expression.Property(entityParam, propertyInfo); if (propertyInfo.PropertyType != typeof(T)) columnExpr = Expression.Convert(columnExpr, typeof(T)); return Expression.Lambda>(columnExpr, entityParam); } 

这将使以下所有调用成功:

 GenerateMemberExpression("Name"); GenerateMemberExpression("Length"); // Reference conversion GenerateMemberExpression("Name"); //Boxing conversion GenerateMemberExpression("Length"); //Lifted conversion GenerateMemberExpression("Length"); 

在传递“对象”的情况下,尝试手动转换字段值。 例如:

 var columnExpr = Expression.MakeMemberAccess(entityParam, fieldPropertyInfo); // {e.fieldName} if (T.GetType().Equals(typeof(object))) { columnExpr = Expression.Convert(columnExpr, typeof(object)); } 

希望这会帮助你。