我正在为REST API构建一个库,以允许动态查询Mongo数据库中的文档。
假设以下Person
实体:
public class Person
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
}
现在,我想创建一个引用动态字段的Expression<Func<TInput, TOutput>>
。
假设一个方法接受2个字符串,1表示要查询的字段,1表示值,此方法可能如下所示:
public Expression<Func<TInput, TOutput>> Create<TInput, TOutput>(string fieldName, string fieldValue)
{
}
当使用Name
这样的单个属性调用上述方法时,可以相对容易地构建表达式:
var parameter = Expression.Parameter(typeof(Person), string.Empty);
var field = Expression.PropertyOrField(parameter, "Name");
var expression = Expression.Lambda<Func<Person, string>>(field, parameter);
但是如何构建一个公开嵌入字段的表达式,例如Address.Street
?
亲切的问候
答案 0 :(得分:0)
您可以查看ExpressionBuilder项目。它可能会帮助您解决您的问题。在FilterBuilder中,您会找到:
string parentName = memberName.Substring(0, memberName.IndexOf("."));
Expression parentMember = helper.GetMemberExpression(param, parentName);
Helper Class中的GetMemberExpression
确实:
因此它基本上在递归中包装多个PropertyExpressions(因为Expression基本上可以是&#34; Address.Street.Number&#34;等等):
public Expression GetMemberExpression(Expression param, string propertyName)
{
if (propertyName.Contains("."))
{
int index = propertyName.IndexOf(".");
var subParam = Expression.Property(param, propertyName.Substring(0, index));
return GetMemberExpression(subParam, propertyName.Substring(index + 1));
}
return Expression.Property(param, propertyName);
}
答案 1 :(得分:0)
试试这个
public static Expression<Func<TEntity, bool>> Predicate<TEntity>(object value, string name, ExpressionType operation = ExpressionType.Equal)
{
var parameter = Expression.Parameter(typeof(TEntity), "entity");
// Getting the names of the properties
var properties = name.Split(".");
//Getting the propety
var property = Expression.Property(parameter, properties[0]);
property = properties.Skip(1).Aggregate(property, Expression.Property);
//Create a Constant Expression for the property value setting its type to be of type of the desired property
var propertyValue = Expression.Constant(value, property.Type);
//Making the comparison
var comparison = Expression.MakeBinary(operation, property, propertyValue);
//Creating the expression lambdaExpression.
var expression = Expression.Lambda<Func<TEntity, bool>>(comparison, parameter);
//Converting the lambdaExpression to required Expression Type
return expression.Cast<TEntity, bool>();
}
public static Expression<Func<TModel, TResult>> Cast<TModel, TResult>(this LambdaExpression expression)
{
return Expression.Lambda<Func<TModel, TResult>>(Expression.Convert(expression.Body, typeof(TResult)), expression.Parameters);
}
public static Expression<Func<TEntity, object>> GetExpression<TEntity>(this string order)
{
var parameter = Expression.Parameter(typeof(TEntity), "entity");
var properties = order.Split(".");
var property = properties.Skip(1).Aggregate(Expression.Property(parameter, properties[0]), Expression.Property);
var expression = Expression.Lambda(typeof(Func<,>).MakeGenericType(typeof(TEntity), property.Type), property, parameter);
return expression.Cast<TEntity, object>();
}