Fra*_*aki 4 c# entity-framework expression-trees
这是我的表情课
public static class ExpressionBuilder
{
private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");
private static MethodInfo startsWithMethod = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
private static MethodInfo endsWithMethod = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
public static Expression<Func<T,
bool>> GetExpression<T>(IList<Filter> filters)
{
if (filters.Count == 0)
return null;
ParameterExpression param = Expression.Parameter(typeof(T), "t");
Expression exp = null;
if (filters.Count == 1)
exp = GetExpression<T>(param, filters[0]);
else if (filters.Count == 2)
exp = GetExpression<T>(param, filters[0], filters[1]);
else
{
while (filters.Count > 0)
{
var f1 = filters[0];
var f2 = filters[1];
if (exp == null)
exp = GetExpression<T>(param, filters[0], filters[1]);
else
exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0], filters[1]));
filters.Remove(f1);
filters.Remove(f2);
if (filters.Count == 1)
{
exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0]));
filters.RemoveAt(0);
}
}
}
return Expression.Lambda<Func<T, bool>>(exp, param);
}
private static Expression GetExpression<T>(ParameterExpression param, Filter filter)
{
MemberExpression member = Expression.Property(param, filter.PropertyName);
ConstantExpression constant = Expression.Constant(filter.Value);
switch (filter.Operation)
{
case Op.Equals:
return Expression.Equal(member, Expression.Call(Expression.Convert(Expression.Constant(search.RetrieveGuid), typeof(object)), typeof(object).GetMethod("ToString"))), constant);
case Op.GreaterThan:
return Expression.GreaterThan(member, constant);
case Op.GreaterThanOrEqual:
return Expression.GreaterThanOrEqual(member, constant);
case Op.LessThan:
return Expression.LessThan(member, constant);
case Op.LessThanOrEqual:
return Expression.LessThanOrEqual(member, constant);
case Op.Contains:
return Expression.Call(member, containsMethod, constant);
case Op.StartsWith:
return Expression.Call(member, startsWithMethod, constant);
case Op.EndsWith:
return Expression.Call(member, endsWithMethod, constant);
}
return null;
}
private static BinaryExpression GetExpression<T>
(ParameterExpression param, Filter filter1, Filter filter2)
{
Expression bin1 = GetExpression<T>(param, filter1);
Expression bin2 = GetExpression<T>(param, filter2);
return Expression.AndAlso(bin1, bin2);
}
}
Run Code Online (Sandbox Code Playgroud)
当我通过此代码生成表达式时
delegExpFilters = EntityExpression.ExpressionBuilder.GetExpression<Contact>(domainFilter).Compile();
Run Code Online (Sandbox Code Playgroud)
我的domainFilter包含具有属性字段名称,操作符及其值的列表记录,而我的字段是GUID
当我调用GetExpression时,给我错误错误没有为类型'System.Guid'和'System.String'定义二进制运算符Equal
您没有将过滤器值(字符串)转换为适当的类型:
ConstantExpression constant = Expression.Constant(filter.Value);
Run Code Online (Sandbox Code Playgroud)
考虑您具有名为的整数属性过滤器Amount:
var filter = new Filter {
PropertyName = "Amount",
Operation = Op.GreaterThan,
Value = "42"
};
Run Code Online (Sandbox Code Playgroud)
您的代码将生成与以下代码等效的表达式
contract.Amount > "42"
Run Code Online (Sandbox Code Playgroud)
不允许将这种整数与字符串进行比较。
您应该获取属性类型并将过滤器值转换为该类型。步骤如下:
objectobject为属性类型这是GetExpression方法的代码
var member = Expression.Property(param, filter.PropertyName);
var propertyType = ((PropertyInfo)member.Member).PropertyType;
var converter = TypeDescriptor.GetConverter(propertyType); // 1
if (!converter.CanConvertFrom(typeof(string))) // 2
throw new NotSupportedException();
var propertyValue = converter.ConvertFromInvariantString(filter.Value); // 3
var constant = Expression.Constant(propertyValue);
var valueExpression = Expression.Convert(constant, propertyType); // 4
Run Code Online (Sandbox Code Playgroud)
您应该在返回的二进制表达式中使用此值表达式而不是常量表达式。例如:
case Op.LessThan:
return Expression.LessThan(member, valueExpression);
case Op.Equal:
return Expression.Equal(member, valueExpression);
// etc
Run Code Online (Sandbox Code Playgroud)
为了平等,您也应该使用二进制表达式。现在,过滤器Amount将被转换为
contract.Amount > (int)42
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6011 次 |
| 最近记录: |