如何使用Expression.Call一个方法调用中我窝的方法调用 [英] How do I nest a call to a method within a call to a method using 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屋!