编程语言
首页 > 编程语言> > c#-动态创建一个选择对象属性的表达式

c#-动态创建一个选择对象属性的表达式

作者:互联网

我希望能够动态构建一个表达式,它本质上是一个属性选择器.

我正在尝试使用它,以便提供灵活的搜索UI,然后将所选的搜索参数转换为Entity Framework查询.

由于使用了另一个库,因此我有了大部分所需的资源,但是缺少最后一部分,该部分将我的查询字符串参数转换为另一个库所需的适当的表达式选择器.

该库的参数为:

Expression<Func<TObject, TPropertyType>>

如果将其烘焙到应用程序中,将如何进行编码的示例如下:

Expression<Func<MyObject, int>> expression = x=> x.IntegerProperty;

但是,我需要能够动态生成该表达式,因为重要的一点是,我所知道的只是对象的类型(MyObject)和属性名称作为字符串值(“ IntegerProperty”).该属性值显然将映射到对象上的属性,该属性可以是任何非复杂类型.

所以本质上,我认为我想找到一种动态构建表达式的方法,该表达式指定要返回的正确对象属性,而返回值由该属性类型确定.

伪代码:

string ObjectPropertyName
Type ObjectType
Type ObjectPropertyType = typeof(ObjectType).GetProperty(ObjectPropertyName).Property

 Expression<Func<[ObjectType], [ObjectPropertyType]>> expression = x=> x.[ObjectPropertyName];

更新:

我到目前为止

ParameterExpression objectParameter = Expression.Parameter(type, "x");
MemberExpression objectProperty = Expression.Property(objectParameter, "PropertyNameString");
Expression<Func<ObjectType, int>> expression = Expression.Lambda<Func<ObjectType, int>>(objectProperty, objectParameter);

但是我的问题是返回类型并不总是int,而可能是其他类型.

解决方法:

按照您的要求进行操作有点棘手,但并非不可能.由于直到运行时才知道属性类型,因此您不能声明Expression< Func<,>.因此可以通过反思来完成.

public static class QueryableExtension
{
    public static object Build<Tobject>(this Tobject source, string propertyName)
    {
        var propInfo = typeof(Tobject).GetProperty(propertyName);

        var parameter = Expression.Parameter(typeof(Tobject), "x");

        var property = Expression.Property(parameter, propInfo);

        var delegateType = typeof(Func<,>)
                           .MakeGenericType(typeof(Tobject), propInfo.PropertyType);

        var lambda = GetExpressionLambdaMethod()
                        .MakeGenericMethod(delegateType)
                        .Invoke(null, new object[] { property, new[] { parameter } });

        return lambda;
    }

    public static MethodInfo GetExpressionLambdaMethod()
    {
       return typeof(Expression)
                     .GetMethods()
                     .Where(m => m.Name == "Lambda")
                     .Select(m => new
                     {
                         Method = m,
                         Params = m.GetParameters(),
                         Args = m.GetGenericArguments()
                     })
                     .Where(x => x.Params.Length == 2
                                 && x.Args.Length == 1
                                 )
                     .Select(x => x.Method)
                     .First();
    }
}

用法-

var expression = testObject.Build("YourPropertyName");

现在,这将使用属性的返回类型来构建所需的表达式.但是由于我们不了解您的库,但是我建议您通过反射来调用您的库方法,并传递包装在对象下的表达式.

标签:c,lambda,expression-trees
来源: https://codeday.me/bug/20191027/1943868.html