2014-09-15 2 views
4

Я работаю над механизмом фильтрации с использованием выражений и не могу понять, как вызвать любой метод, используя Expression.Call. Ниже приведен пример, который не имеет смысла, но иллюстрирует мою проблему:Expression.Call with Any method throws exception

var person = new List<String>(new[] { "Peter", "John", "Jim" }); 
var personQuery = person.AsQueryable(); 

var anyMethod = typeof(Queryable).GetMethods().FirstOrDefault(method => method.Name == "Any" && method.GetParameters().Count() == 2); 

Expression<Func<String, bool>> expr = p => p == "Amy"; 

// person.Any(person => person == "Amy" 
var call = Expression.Call(
    anyMethod, 
    personQuery.Expression, 
    expr 
); 

Expression.Call бросает ArgumentException:

System.ArgumentException was unhandled 
    HResult=-2147024809 
    Message=Method Boolean Any[TSource](System.Linq.IQueryable`1[TSource], System.Linq.Expressions.Expression`1[System.Func`2[TSource,System.Boolean]]) is a generic method definition. 
    Source=System.Core 
    StackTrace: 
     w System.Linq.Expressions.Expression.ValidateMethodInfo(MethodInfo method) 
     w System.Linq.Expressions.Expression.ValidateMethodAndGetParameters(Expression instance, MethodInfo method) 
     w System.Linq.Expressions.Expression.Call(MethodInfo method, Expression arg0, Expression arg1) 
     w TestConsoleApplication.Program.Main(String[] args) w d:\Users\user\Documents\Visual Studio 2012\Projects\TestConsoleApplication\TestConsoleApplication\Program.cs:wiersz 26 
     w System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     w System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     w Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     w System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     w System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
     w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
     w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     w System.Threading.ThreadHelper.ThreadStart() 
    InnerException: 
+2

Не могли бы вы перевести текст сообщения об исключении на английский язык для нас? –

+0

Сообщение об исключении. – PaulP

ответ

7

Ваш anyMethod переменная будет содержать общее определение метода. I.e Any<TSource> вам нужно будет преобразовать его в Any<String>, прежде чем использовать его.

Вы сделаете это, позвонив по номеру anyMethod.MakeGenericMethod, указав аргумент typeof(String). Таким образом, ваш код становится

var person = new List<String>(new[] { "Peter", "John", "Jim" }); 
var personQuery = person.AsQueryable(); 

var anyMethod = typeof(Queryable).GetMethods().FirstOrDefault(method => method.Name == "Any" && method.GetParameters().Count() == 2); 
var specificMethod = anyMethod.MakeGenericMethod(typeof(String));//<--Important 
Expression<Func<String, bool>> expr = p => p == "Amy"; 

// person.Any(person => person == "Amy" 
var call = Expression.Call(
    specificMethod, 
    personQuery.Expression, 
    expr 
); 
Смежные вопросы