Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq expression tree string comparison

I am trying to construct an expression tree to operate against a string array. I need to figure out how to use the Equal method.

Could anyone give me an example of
1) using the Expression.Equal (or .Equals) method to compare a string to a constant, and
2) using an Expression of whatever sort to use the string.Contains() method for filtering purposes.

I am trying to learn the Expression Tree mechanics, but as of yet, I have not found a good tutorial. I greatly appreciate your help.

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);
like image 223
Sako73 Avatar asked Jun 01 '26 21:06

Sako73


1 Answers

Aaah, I see what you are asking... And you're really entering some very murky waters, one of the few areas that the .NET reflection libraries aren't beautiful to work with. You have to create a call expression to call Queryable.Where() on the queryableData object, and create a new query using that expression... The problem is that getting a generic version of a method in .NET isn't necessarily the easiest thing you've ever run across in your life:

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

You would also have to define getGenericMethod (you can find better implementations for this online at other places, this is really quite a simple approach):

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

There are almost undoubtedly a few errors in there, but I hope you can see where to go from there...

like image 174
LorenVS Avatar answered Jun 04 '26 12:06

LorenVS



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!