Почему Expression.Call генерирует ошибку параметров - PullRequest
0 голосов
/ 11 апреля 2019

Я пытаюсь извлечь метод Count, чтобы потом использовать его для построения дерева выражений.

var g = Expression.Parameter(typeof(IEnumerable<float?>), "g");
var countMethod = typeof(Enumerable)
    .GetMethods()
    .Single(m => m.Name == "Count" && m.GetParameters().Count() == 1);
var countMaterialized = countMethod
    .MakeGenericMethod(new[] { g.Type });
var expr = Expression.Call(countMaterialized, g);

Выдает эту ошибку:

System.ArgumentException: 'выражение типа' System.Collections.Generic.IEnumerable 1[System.Nullable 1 [System.Single]] 'нельзя использовать для параметра типа' System.Collections.Generic.IEnumerable 1[System.Collections.Generic.IEnumerable 1 [ System.Nullable 1[System.Single]]]' of method 'Int32 Count[IEnumerable1](System.Collections.Generic.IEnumerable 1 [System.Collections.Generic.IEnumerable 1[System.Nullable 1 [System.Single]]]) ''

Чего мне не хватает?

1 Ответ

0 голосов
/ 12 апреля 2019

Ваш тип параметра правильный, но ваш общий тип должен быть "float?"вместо "IEnumerable".

var g = Expression.Parameter(typeof(IEnumerable<float?>), "g");

// get the method definition using object as a placeholder parameter
var countMethodOfObject = ((Func<IEnumerable<object>, int>)Enumerable.Count<object>).Method;

// get the generic method definition
var countMethod = countMethodOfObject.GetGenericMethodDefinition();

// create generic method
var countMaterialized = countMethod.MakeGenericMethod(new[] { typeof(float?) });

// creare expression
var countExpression = Expression.Call(countMaterialized, g);

var expression = Expression.Lambda<Func<IEnumerable<float?>, int>>(countExpression, g);

IEnumerable<float?> floats = Enumerable.Range(3, 5).Select(v => (float?)v);
var count = expression.Compile().Invoke(floats);
...