动态MemberExpression [英] Dynamic MemberExpression

查看:128
本文介绍了动态MemberExpression的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am wanting to create a MemberExpression knowing only the field name; eg:

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;
    }

上面的问题是字段类型必须是强类型的。传递对象作为字段类型不起作用。有没有办法产生这个?即使是动态LINQ也不会起作用。

The problem with the above is that the field type must be strongly typed. Passing "object" in as the field type doesn't work. Is there any way to generate this? Even Dynamic LINQ doesn't appear to work.

推荐答案

您的代码有一些问题:


  1. 您的方法的参数称为 fieldName ,但您正在获取属性<使用它。

  2. 您正在使用非通用的 Expression.Lambda 方法来生成表达式,可以选择如果传递给该方法的type-argument T 与属性类型不同,则不适当的委托类型。在这种情况下,从表达式到方法的返回类型的转换将失败并计算为 null 。解决方案:使用通用 Lambda 方法与适当的类型参数。

  3. 如果您解决第二个问题,当可以从property-type到 T ,但是如果需要更复杂的转换,例如拳击/提升。解决方案:使用 Expression.Convert 方法。

  1. The parameter to your method is called fieldName, but you are getting a property out with it.
  2. You are using the non-generic Expression.Lambda method to generate the expression, which may choose an inappropriate delegate-type if the type-argument T passed to the method is not the same as the property-type. In this case, the as cast from the expression to the method's return-type will fail and evaluate to null. Solution: Use the generic Lambda method with the appropriate type-arguments. No casting required.
  3. If you solve the second issue, things will work fine when a safe reference-conversion is available from the property-type to T, but not when more complicated conversions such as boxing / lifting are required. Solution: Use the Expression.Convert method where necessary.






以下是解决这些问题的示例的更新:


Here's an update to your sample that addresses these issues:

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);
}

这将使所有以下呼叫成功:

This will make all of the following calls succeed:

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");

这篇关于动态MemberExpression的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆