Lambda and Expression.Call for an extension method

10,070

Solution 1

Try this

public class Person
{
    public string Name { get; set; }
}
public static class StringEx
{
    public static bool Like(this string a, string b)
    {
        return a.ToLower().Contains(b.ToLower());
    }
}

Person p = new Person(){Name = "Me"};
var prop = Expression.Property(Expression.Constant(p), "Name");
var value = Expression.Constant("me");
var like = typeof(StringEx).GetMethod("Like", BindingFlags.Static
                        | BindingFlags.Public | BindingFlags.NonPublic);
var comparer = Expression.Call(null, like, prop, value );

var vvv = (Func<bool>) Expression.Lambda(comparer).Compile();
bool isEquals = vvv.Invoke();

Solution 2

You can do like this:

var like = typeof(StringEx).GetMethod("Like", new[] {typeof(string), typeof(string)});

comparer = Expression.Call(null, like, prop, value);

You can pass prop as first parameter and value as second parameter like above.

Maybe you will need to get a complete query before apply an extension method.

Solution 3

I am not sure, but you can only get an extension method from the static class using reflection. Extension methods are not truly added to the class, therefore can't be retrieved with GetMethod.

Solution 4

Use

var like = typeof(StringEx).GetMethod("Like", new[] {typeof(string),typeof(string)});

ie. retrieve it from the extending type, not from the extended type.

Share:
10,070
CodeAddicted
Author by

CodeAddicted

Updated on July 29, 2022

Comments

  • CodeAddicted
    CodeAddicted over 1 year

    I need to implement an expression for a method like here:

    var prop = Expression.Property(someItem, "Name"); 
    var value = Expression.Constant(someConstant);
    
    var contains = typeof(string).GetMethod("Contains", new[] {typeof(string)});
    var expression = Expression.Call(prop, contains, value);
    

    But for my extension method:

    public static class StringEx
    {
        public static bool Like(this string a, string b)
        {
            return a.ToLower().Contains(b.ToLower());
        }
    }
    

    Unfortunately, next code throws an ArgumentNullException for a parameter "method":

    var like = typeof(string).GetMethod("Like", new[] {typeof(string)});
    comparer = Expression.Call(prop, like, value);
    

    What I'm doing wrong?

  • CodeAddicted
    CodeAddicted almost 12 years
    Thanks, I suppose I need to call GetMethod this way: typeof(StringEx).GetMethod("Like", new[] {typeof(string)}); but how I have to inject my parameters in Expression.Call?
  • CodeAddicted
    CodeAddicted almost 12 years
    Thanks a lot, but this throws an argument exception: Need null instance for static method, so I need some magic with BindingFlags.Static, but this is outside from my comprehension(
  • Minustar
    Minustar almost 12 years
    See @Lonli-Lokli's answer below.
  • Tyler Burki
    Tyler Burki almost 7 years
    This makes sense and is exactly what I needed, thank you.