Lambda和Expression.Call用于扩展方法

时间:2011-12-01 07:17:34

标签: c# .net lambda extension-methods expression-trees

我需要为这样的方法实现一个表达式:

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

但对于我的扩展方法:

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

不幸的是,下一个代码会为参数“method”抛出ArgumentNullException:

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

我做错了什么?

5 个答案:

答案 0 :(得分:14)

试试这个

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

答案 1 :(得分:4)

你可以这样做:

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

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

您可以将prop作为第一个参数传递,将value作为第二个参数传递,如上所述。

在应用扩展方法之前,您可能需要获得完整的查询。

答案 2 :(得分:2)

我不确定,但您只能使用反射从静态类中获取扩展方法。扩展方法并未真正添加到类中,因此无法使用GetMethod检索。

答案 3 :(得分:1)

使用

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

即。从扩展类型中检索它,而不是从扩展类型中检索它。

答案 4 :(得分:0)

如果您希望扩展方法有效,您必须这样做:

string str = "some string";
str.Like("second string");