动态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.

推荐答案

有一些与你的代码问题:

There are a number of issues with your code:


  1. 参数到你的方法被称为字段名,但你得到一个的属性出它。

  2. 您正在使用非通用 Expression.Lambda 方法生成的表达,这可能会选择一个不适当的委托类型,如果类型参数 T 传递给方法是不一样的属性类型。在这种情况下,从表达投的方法的返回类型将失败,并计算为。解决方法:使用通用 LAMBDA 方法用适当的类型参数。无需铸造。

  3. 如果您解决第二个问题,事情会正常工作时的安全基准转换,可以从物业类型为 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天全站免登陆