不能调用参数类型为A的A类方法?

时间:2016-08-16 05:34:00

标签: c# linq expression-trees

所以我不太明白这一点。我试图创建一个MethodCallExpression,但是我收到一个运行时错误,说明该方法无法使用它所期望的类型进行调用?我对表达树很新,所以我确定我有一些倒退的东西,但几乎每一个我尝试适应的例子都会导致这种情况。

using System;
using System.Linq;
using System.Linq.Expressions;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            var helper = new Helper();
            var expr = helper.GetMatchExpr<TestClass>(t => t.Name, "foo");
        }
    }

    public class Helper
    {
        public Expression<Func<T, bool>> GetMatchExpr<T>(Expression<Func<T, object>> member, string searchValue)
        {
            var memberExpr = member.Body as MemberExpression;
            if (memberExpr == null)
                throw new ArgumentException("Expected member expression");

            var parameter = Expression.Parameter(typeof(T), "type");
            var property = Expression.Property(parameter, memberExpr.Member.Name);
            var propertyExpr = Expression.Convert(property, typeof(string));

            var matchMethod = typeof(Helper).GetMethod("IsMatch", new[] { typeof(object), typeof(string) });

            var valueExpr = Expression.Constant(searchValue, typeof(string));
            var matchExpr = Expression.Call(property, matchMethod, propertyExpr, valueExpr); // throws exception

            return Expression.Lambda<Func<T, bool>>(matchExpr, parameter);
        }

        public bool IsMatch(object input, string searchValue)
        {
            if (input == null)
                return true;

            var qWords = GetWords(searchValue);
            var pWords = GetWords(input.ToString());

            return (
                from qWord in qWords
                from pWord in pWords
                where qWord.Equals(pWord, StringComparison.OrdinalIgnoreCase)
                select qWord).Any();
        }

        public string[] GetWords(string input)
        {
            return string.IsNullOrEmpty(input)
                ? new string[0]
                : input.Split(' ');
        }
    }

    public class TestClass
    {
        public string Name { get; set; }
        public string Age { get; set; }
    }
}

例外是

  

附加信息:方法&#39;布尔IsMatch(System.Object)&#39;   在类型上声明   &#39; ConsoleApplication4.Helper`1 [ConsoleApplication4.TestClass]&#39;不能   使用类型&System;对象&#39;

的实例调用

回答一些问题:

作为练习,我尝试将此类构建到可以在对象T上指定将包含在搜索中的属性集合的位置。因此,一旦设置了所有这些属性,就调用Apply(...),它将遍历成员表达式的集合,获取它们的值,将其拆分为单个单词,对查询短语执行相同操作然后返回任何对象具有与任何单词匹配的任何属性。

我经历过5到6个不同的例子,这些例子看起来与我想要达到的目标非常接近,这就是我现在所处的位置。

所以我想我并不完全理解&#34;在PropertyExpr&#34;的结果上调用IsMatch。这是否意味着它使用result.IsMatch或IsMatch(结果)等结果?如果它是后者,那么不应该将任何东西用作对象吗?

1 个答案:

答案 0 :(得分:1)

查看你的方法调用表达式:

var matchExpr = Expression.Call(property, matchMethod, propertyExpr, valueExpr);

第一个参数是方法调用的目标 - 您尝试调用IsMatch的内容。现在IsMatch在您的助手类中声明,因此您应该在该类的实例上调用它。例如:

var targetExpr = Expression.Constant(this, typeof(Helper));
var matchExpr = Expression.Call(targetExpr, matchMethod, propertyExpr, valueExpr);

删除了例外 - 但它仍然不清楚这些代码是否会对你有所帮助。当表达式树可以转换成某种其他形式时,例如具有查询的表达式树表示通常是有用的。 SQL ...但没有LINQ提供程序会知道你的Helper.IsMatch方法做了什么。

如果您的目标是在数据库中完成所有匹配工作,那么此解决方案无法帮助您。如果您的目标只是进行匹配工作,那么您可以更简单地使用LINQ to Objects,只需适当地调用方法并在需要时使用委托,而不必使用IQueryable<T>