动态创建一个选择对象属性的表达式 [英] Dynamically creating an expression which selects an objects property
问题描述
我希望能够动态构建一个表达式,它本质上是一个属性选择器.
I want to be able to build up an expression dynamically, which is essentially a property selector.
我正在尝试使用它,以便提供灵活的搜索UI,然后将所选的搜索参数转换为Entity Framework查询.
I am trying to use this so I can provide a flexible search UI and then translate the selected search parameters to an Entity Framework query.
由于我正在使用另一个库,因此我有大部分需要,但是缺少最后一部分,该部分将我的查询字符串参数转换为另一个库所需的适当的表达式选择器.
I have most of what I need thanks to another library I am using, but am missing the final part which translates my query string parameters to the appropriate expression selector the other library requires.
该库的参数为:
Expression<Func<TObject, TPropertyType>>
如果将其烘焙到应用程序中,将如何对其进行编码的示例如下:
An example of how this would be coded if baked into an application would be :
Expression<Func<MyObject, int>> expression = x=> x.IntegerProperty;
但是,我需要能够动态生成此表达式,因为重要的一点是,我所知道的只是对象的类型(MyObject)和属性名称作为字符串值("IntegerProperty").该属性值显然将映射到对象上的属性,该属性可以是任何非复杂类型.
However, I need to be able to generate this expression dynamically, as the important point is that all I will know is the type of object (MyObject) and the property name as a string value ("IntegerProperty"). The property value will obviously map to an property on the object which could be of any non complex type.
所以本质上,我认为我想找到一种动态构建表达式的方法,该表达式指定要返回的正确对象属性,并且返回值由该属性类型确定.
So essentially I think I am wanting to find a way to build up the expression dynamically which specifies the correct object property to return and where the return value is determined by that property type.
伪代码:
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,而可能是其他类型.
But the problem I have with this is that the return type is not always an int but may be some other type.
推荐答案
按照您的要求做的事情有些棘手,但并非没有可能.由于属性类型直到运行时才知道,因此您无法声明Expression<Func<,>>
,因此可以通过反射来完成.
Doing what you asked is bit tricky but not impossible. Since the property type is not known until run time so you can not declare the Expression<Func<,>>
so it would be done by reflection.
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");
现在,这将使用属性的返回类型来构建所需的表达式.但是,由于我们不了解您的库,但是我建议您通过反射来调用您的库方法,并传递包装在对象下的表达式.
Now this will build the Expression you desired with return type of property. But since we don't know about your library but I suggest you to call your library method via reflection and pass the expression wrapped under object.
这篇关于动态创建一个选择对象属性的表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!