【问题标题】:Lambda and Expression.Call for an extension methodLambda 和 Expression.Call 用于扩展方法
【发布时间】:2011-12-01 07:17:34
【问题描述】:

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

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

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

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

我做错了什么?

【问题讨论】:

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


【解决方案1】:

试试这个

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

【讨论】:

    【解决方案2】:

    你可以这样做:

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

    您可以像上面一样将prop 作为第一个参数,将value 作为第二个参数。

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

    【讨论】:

    • 这很有道理,正是我所需要的,谢谢。
    【解决方案3】:

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

    【讨论】:

    • 谢谢,我想我需要这样调用 GetMethod:typeof(StringEx).GetMethod("Like", new[] {typeof(string)}); 但是我必须如何在 Expression.Call 中注入我的参数?
    • 见下面@Lonli-Lokli 的回答。
    【解决方案4】:

    使用

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

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

    【讨论】:

    • 非常感谢,但这会引发参数异常:静态方法需要空实例,所以我需要 BindingFlags.Static 的一些魔法,但这超出了我的理解范围(
    【解决方案5】:

    如果你想让你的扩展方法起作用,你必须这样做:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多