如何使用Expression.Call一个方法调用中我窝的方法调用 [英] How do I nest a call to a method within a call to a method using Expression.Call

查看:1005
本文介绍了如何使用Expression.Call一个方法调用中我窝的方法调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想一个DateTime转换为字符串之前调用包含它。然而,尽管我的推杆一个表达式的结果到另一个的努力我惨遭失败。

I am trying to convert a DateTime to a String before calling contains on it. However despite my efforts of putting the result of one expression into another I fail miserably.

的代码从最高应答所得出此问题用asp.net的WebMethod和JSON排序,分页,搜索和LINQ工作的jqGrid - 但需要动态运营商

The code is derived from the highest answer to this question jqgrid with asp.net webmethod and json working with sorting, paging, searching and LINQ — but needs dynamic operators.

假设我从<一个下列方法StringExtension HREF =http://stackoverflow.com/questions/2413032/jqgrid-with-asp-net-webmethod-and-json-working-with-sorting-paging-searching-an称号=使用的jqGrid的WebMethod asp.net和JSON排序,分页,搜索和LINQ的工作 - 但需要动态操作>问题:

public static class StringExtensions
{
  public static MemberExpression ToMemberExpression(this string source, ParameterExpression p)
  {
    if (p == null)
        throw new ArgumentNullException("p");

    string[] properties = source.Split('.');

    Expression expression = p;
    Type type = p.Type;

    foreach (var prop in properties)
    {
        var property = type.GetProperty(prop);
        if (property == null)
            throw new ArgumentException("Invalid expression", "source");

        expression = Expression.MakeMemberAccess(expression, property);
        type = property.PropertyType;
    }

    return (MemberExpression)expression;
  }
}



因此,我有以下的方法也由<一个HREF =http://stackoverflow.com/questions/2413032/jqgrid-with-asp-net-webmethod-and-json-working-with-sorting-paging-searching-an称号=使用的jqGrid的WebMethod asp.net和JSON排序,分页,搜索和LINQ的工作 - 但需要动态操作>问题我已经那么适合的DateTime

Therefore I have the following method also from the question which I have then adapted for DateTime.

public virtual Expression<Func<T, bool>> CreateExpression<T>(string searchField, string searchString, string searchOper)
    {
        Expression exp = null;
        var p = Expression.Parameter(typeof(T), "p");

        Expression propertyAccess = searchField.ToMemberExpression(p);

        switch (searchOper)
        {
            case "bw":
                exp = Expression.Call(propertyAccess, typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) }), Expression.Constant(searchString));
                break;

            // New code by me
            case "cn":

                if (propertyAccess.Type == typeof(DateTime))
                {
                    // My faulty logic - from Jon Skeet answer below

                    Expression toStringCall = Expression.Call(
                        propertyAccess, "ToString",
                        null,
                        new[] { Expression.Constant("D") });

                    Expression containsCall = Expression.Call(
                        toStringCall, "Contains",
                        null,
                        new[] { Expression.Constant(searchString) });

                    exp = containsCall;
                }
                else
                {
                    // Unchanged
                    exp = Expression.Call(propertyAccess, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), Expression.Constant(searchString));
                }
                break;
            case "ew":
                exp = Expression.Call(propertyAccess, typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) }), Expression.Constant(searchString));
                break;
            case "gt":
                exp = Expression.GreaterThan(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
                break;
            case "ge":
                exp = Expression.GreaterThanOrEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
                break;
            case "lt":
                exp = Expression.LessThan(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
                break;
            case "le":
                exp = Expression.LessThanOrEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
                break;
            case "eq":
                exp = Expression.Equal(propertyAccess, Expression.Constant(searchString.ToType(propertyAccess.Type), propertyAccess.Type));
                break;
            case "ne":
                exp = Expression.NotEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
                break;
            default:
                return null;
        }

        return (Expression<Func<T, bool>>)Expression.Lambda(exp, p);
    }



我得到下面的异常。

I get the following exception.

LINQ到实体无法识别方法'System.String的ToString(System.String)的方法,而这种方法不能被翻译成店的表情。

LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.

推荐答案

我的犯罪嫌疑人的你想这样的事情(从以前版本的固定):

I suspect you want something like this (fixed from previous version):

using System;
using System.Linq.Expressions;

public class Person
{
    public DateTime DateOfBirth { get; set; }
}

public class Test
{
    static void Main()
    {
        var expr = Foo<Person>("DateOfBirth", "1976");

        Person p = new Person
        {
            DateOfBirth = new DateTime(1976, 6, 19)
        };

        Console.WriteLine(expr.Compile()(p));
    }

    static Expression<Func<T, bool>> Foo<T>(string propertyName,
                                            string searchValue)
    {
        ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
        Expression property = Expression.Property(parameter, propertyName);
        Expression toStringCall = Expression.Call(
            property, "ToString",
            null,
            new[] { Expression.Constant("D") });

        Expression containsCall = Expression.Call(
            toStringCall, "Contains",
            null,
            new[] { Expression.Constant(searchValue) });

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

请注意,该空值,以表明这是一个非泛型方法调用。

Note that the "null" values are to show that it's a non-generic method call.

这篇关于如何使用Expression.Call一个方法调用中我窝的方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆