为什么Expression.Call抛出参数错误

时间:2019-04-11 14:21:46

标签: c# linq generics reflection expression

我正在尝试提取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 }} 1 [System.Nullable 1[System.Collections.Generic.IEnumerable 1 [System.Collections.Generic.IEnumerable 1[System.Single]]]' of method 'Int32 Count[IEnumerable1](System.Collections.Generic.IEnumerable 1 [System.Single]]])'')

我想念什么?

1 个答案:

答案 0 :(得分:0)

您的参数类型正确,但是您的通用类型应该为“ 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);