Linq表达式树字符串比较

3
我正在尝试构建一棵表达式树,用于操作字符串数组。我需要弄清如何使用Equal方法。
谁能给我提供以下示例: 1)使用Expression.Equal(或.Equals)方法将字符串与常量进行比较,并且 2)使用任何类型的Expression来使用string.Contains()方法进行过滤。
我正在尝试学习Expression Tree的机制,但迄今为止,我还没有找到一个好的教程。非常感谢您的帮助。
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);

你走在正确的轨道上了... 在比较之后出现的部分绝对是构造函数LINQ表达式中最不直观的部分。希望我的回答能有所帮助... - LorenVS
2个回答

3

啊,我明白你的问题了...你正在涉足一些非常混浊的领域,这是.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;
}

这里几乎肯定存在一些错误,但我希望您能从中看出需要进行哪些改进...


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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接