动态MemberExpression

joh*_*boy 9 c# linq dynamic expression-trees

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

public static Expression<Func<TModel, T>> GenerateMemberExpression<TModel, T>(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<TModel, T>>; // {e => e.column}

        return lambda;
    }
Run Code Online (Sandbox Code Playgroud)

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

Ani*_*Ani 20

您的代码存在许多问题:

  1. 调用方法的参数fieldName,但是您正在使用它获取属性.
  2. 您正在使用非通用Expression.Lambda方法来生成表达,这可能会选择不合适的委托类型,如果类型参数T传递给方法是不一样的属性类型.在这种情况下,as从表达式到方法的返回类型的强制转换将失败并进行求值null.解决方案:将泛型 Lambda方法与相应的类型参数一起使用.不需要铸造.
  3. 如果解决第二个问题,事情会正常工作时的安全基准转换可从财产类型T,而不是当需要更复杂的转换,如拳击/吊装.解决方案:Expression.Convert在必要时使用该方法.

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

public static Expression<Func<TModel, T>> GenerateMemberExpression<TModel, T>
   (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<Func<TModel, T>>(columnExpr, entityParam);
}
Run Code Online (Sandbox Code Playgroud)

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

GenerateMemberExpression<FileInfo, string>("Name");
GenerateMemberExpression<string, int>("Length");

// Reference conversion
GenerateMemberExpression<FileInfo, object>("Name");          

//Boxing conversion
GenerateMemberExpression<string, object>("Length");

//Lifted conversion
GenerateMemberExpression<string, int?>("Length");
Run Code Online (Sandbox Code Playgroud)

  • 谢谢@Ani.帮了我一点.对于我自己的代码,我还添加了一个采用propertyInfo而不是propertyName的方法. (2认同)