繁体   English   中英

无法使用参数类型A调用类型A的方法吗?

[英]Cannot call method of type A with parameter type A?

所以我不太明白这一点。 我正在尝试创建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; }
    }
}

例外是

附加信息:类型为“ System.Object”的实例不能调用在类型为“ ConsoleApplication4.Helper`1 [ConsoleApplication4.TestClass]”上声明的方法“ Boolean IsMatch(System.Object)”

要回答一些问题:

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

我经历了大约5或6个不同的示例,这些示例看起来与我想要实现的目标非常接近,而这正是我目前所处的位置。

所以我想我不太明白“在propertyExpr的结果上调用IsMatch”。 这是否意味着它正在使用诸如result.IsMatch或IsMatch(result)之类的结果? 如果是后者,那么任何东西都不能用作对象吗?

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

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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM