Linq表达式树字符串比较

时间:2009-12-11 20:19:27

标签: linq expression-trees

我正在尝试构造一个表达式树来对字符串数组进行操作。我需要弄清楚如何使用Equal方法。

有谁可以给​​我一个例子 1)使用Expression.Equal(或.Equals)方法将字符串与常量进行比较,并使用 2)使用任何排序的表达式来使用string.Contains()方法进行过滤。

我正在尝试学习表达式树的机制,但到目前为止,我还没有找到一个好的教程。非常感谢你的帮助。

string[] arr = {"s1","s2","s3"};
IQueryable<String> queryableData = arr.AsQueryable<string>();

// what should go below here?
ParameterExpression p1 = Expression.Parameter(typeof(string), "c");
Expression left = Expression.Constant("s2");
Expression e1 = Expression.Equal(left, p1);

IQueryable<string> res = queryableData.Provider.CreateQuery<string>(e2);

2 个答案:

答案 0 :(得分:3)

Aaah,我明白你在问什么...而且你真的进入了一些非常模糊的水域,这是.NET反射库不适合使用的少数几个领域之一。您必须创建一个调用表达式来调用queryableData对象上的Queryable.Where(),并使用该表达式创建一个新查询...问题是在.NET中获取方法的泛型版本不一定是最简单的你生活中遇到过的事情:

MethodCallExpression call = Expression.Call(
    null, // Calling Queryable.Where(), extension method, not instance method
    getGenericMethod<string>(typeof(Queryable), "Where", typeof(IQueryable<string>), typeof(Expression<Func<string,bool>>)),
    Expression.Constant(queryableData),
    Expression.Lamda(
       e1,
       p1)
);
IQueryable<string> res = queryableData.Provider.CreateQuery<string>(call);

您还必须定义getGenericMethod(您可以在其他地方找到更好的在线实现,这是一个非常简单的方法):

private static MethodInfo getGenericMethod<T>(Type type, string name, params Type[] paramTypes)
{
    MethodInfo[] methods = type.GetMethods(name);
    foreach(MethodInfo mi in methods)
    {
        if(!mi.IsGenericMethodDefinition) // or some similar property
            continue;
        if(mi.GetGenericArguments().Length != 1)
            continue;
        if(mi.GetParameters().Length != paramTypes.Length)
            continue;


        MethodInfo genMethod = mi.MakeGenericMethod(new Type[]{typeof(T)});
        var ps = genMethod.GetParameters();
        bool isGood = true;
        for(int i = 0; i < ps.Length; i++)
        {
            if(ps[i].ParameterType != paramTypes[i])
            {
               isGood = false;
               break;
            }
        }

        if(isGood)
            return genMethod;

    }

    return null;
}

那里几乎无疑有一些错误,但我希望你能从那里看到去哪里......

答案 1 :(得分:0)

只是提出我的解决方案:

string[] arr = {"s1","s2","s3"};
IQueryable<String> queryableData = arr.AsQueryable<string>();
ParameterExpression pe = Expression.Parameter(typeof(string), "company");
Expression right = Expression.Constant("on");
Expression left = Expression.Call(pe, typeof(string).GetMethod("Contains"), right);
MethodCallExpression e2 = Expression.Call(
            typeof(Queryable),
            "Where",
            new Type[] { queryableData.ElementType },
            queryableData.Expression,
            Expression.Lambda<Func<string, bool>>(left, new ParameterExpression[] { pe }));

IQueryable<string> res = queryableData.Provider.CreateQuery<string>(e2);