开发者

Compare with string values using IQueryable<T> and Expressions

开发者 https://www.devze.com 2023-02-12 13:41 出处:网络
Sorry about the title but I can\'t really think of a quick way of saying what I want - could someone please change it to a more appropriate one if you think of one?

Sorry about the title but I can't really think of a quick way of saying what I want - could someone please change it to a more appropriate one if you think of one?

I'm trying to turn the following function call into an expression query.

List.Compare("propretyName", ">1000");


public static IQueryable<T> Compare<T>(this IQueryable<T> source, s开发者_JAVA技巧tring propertyName, string value) {
    Type type = typeof(T);
    ParameterExpression parameter = Expression.Parameter(type, "param");
    MemberExpression memberAccess = Expression.MakeMemberAccess(parameter, type.GetProperty(propertyName));

    string comparisonType = value.Substring(0, 1);
    value = value.Length > 0 ? value.Substring(1) : "0";

    decimal tmpvalue;
    decimal? result = decimal.TryParse(value, out tmpvalue) ? tmpvalue : (decimal?)null;
    ConstantExpression constant = Expression.Constant(result, typeof(decimal?));
    BinaryExpression comparisonExpression = Expression.GreaterThan(memberAccess, constant);
    switch (comparisonType) {
        case ">":
            comparisonExpression = Expression.GreaterThan(memberAccess, constant);
            break;
        case "<":
            comparisonExpression = Expression.LessThan(memberAccess, constant);
            break;
        case "=":
            comparisonExpression = Expression.Equal(memberAccess, constant);
            break;
    }

    Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(comparisonExpression, parameter);
    return source.Where(lambda);
}

The above is the method I wrote to make that call.

The lambda at the bottom appears to be correct: {param => (param.propretyName > 1000)}

However, it's not working and I think it's because the particular proprety I'm working on is a decimal? so it should be {param => (param.propertyName.Value > 1000)}.

Could anybody help me out to use the Value rather than. There's just something that's escaping me here.

I can't use the Where(string) method as I'm using Entity-Framework.

Answer found

public static IQueryable<T> Compare<T>(this IQueryable<T> source, string propertyName, string value) {
    Type type = typeof(T);
    ParameterExpression parameter = Expression.Parameter(type, "param");
    MemberExpression memberAccess = Expression.MakeMemberAccess(parameter, type.GetProperty(propertyName));

    //This is the added methods that results in the proper output
    PropertyInfo valProp = typeof(Nullable<decimal>).GetProperty("Value");
    memberAccess = Expression.MakeMemberAccess(memberAccess, valProp);

    string comparisonType = value.Substring(0, 1);
    value = value.Length > 0 ? value.Substring(1) : "0";

    decimal tmpvalue;
    decimal? result = decimal.TryParse(value, out tmpvalue) ? tmpvalue : (decimal?)null;
    ConstantExpression constant = Expression.Constant(tmpvalue);
    BinaryExpression comparisonExpression = Expression.GreaterThan(memberAccess, constant);
    switch (comparisonType) {
        case ">":
            comparisonExpression = Expression.GreaterThan(memberAccess, constant);
            break;
        case "<":
            comparisonExpression = Expression.LessThan(memberAccess, constant);
            break;
        case "=":
            comparisonExpression = Expression.Equal(memberAccess, constant);
            break;
    }

    Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(comparisonExpression, parameter);
    return source.Where(lambda);
}


Why not just use the existing Dynamic LINQ library:

myList.Where("propertyName > 1000");
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号