无法在Expression.Call

时间:2016-01-11 10:02:50

标签: c# linq lambda expression-trees

这是我的班级:

class SampleExpression
{
    public static void SampleEnum(IEnumerator<string> ien)
    {
        while (ien.MoveNext())
        {
            Console.WriteLine(ien.Current);
        }
    }
}

这就是我试图调用SampleEnum方法的方法:

    public void Main(string[] args)
    {
        ParameterExpression param2 = Expression.Parameter(typeof(SampleExpression), "args");

        var lstConstant = "1,2,3,4,".Split(new string[] { "," },
                                                StringSplitOptions.RemoveEmptyEntries).ToList();

        Expression ep = Expression.Constant(Expression.Constant(lstConstant, typeof(IEnumerable<string>)));
        var enummethod = typeof(SampleExpression).GetMethod("SampleEnum");
        MethodCallExpression methodCall = Expression.Call
                                        (
                                            enummethod
                                            , ep
                                        );

        var e = Expression.Lambda<Func<IEnumerator<string>, string>>(methodCall, param2);
        e.Compile()(lstConstant.GetEnumerator());
    }

我在尝试创建方法调用表达式的行中收到以下错误:

  

'System.Linq.Expressions.TypedConstantExpression'类型的表达式不能用于'System.Collections.Generic.IEnumerator 1[System.String]' of method 'Void Enum(System.Collections.Generic.IEnumerator 1 [System.String])'

类型的参数

请帮忙。

1 个答案:

答案 0 :(得分:3)

您似乎非常困惑 - 查看C#编译器如何生成类似的表达式树可能会有所帮助。无论如何,你犯了一些错误:

  • IEnumerable<T>不是IEnumerator<T>。它们不可互换。
  • param2是一个带SampleExpression的参数表达式,而你的lambda实际上需要IEnumerator<string>
  • ep是常量表达式的常量表达式。那不是你想要的。删除外部Expression.Constant
  • 实际上并未实际使用lambda参数 - 您只能使用Func<string>代替Func<IEnumerator<string>, string>
  • 您的表达式树没有返回值,而lambda期望返回string

假设你想拥有一个IEnumerator<string>并使用它来调用SampleExpression.SampleEnum的lambda,你可以使用这样的东西:

public void Test()
{
    var enumeratorParameter 
        = Expression.Parameter(typeof(IEnumerator<string>), "enumerator");

    var sampleEnumMethod = typeof(SampleExpression).GetMethod("SampleEnum");
    var methodCall = Expression.Call(sampleEnumMethod, enumeratorParameter);

    var e = Expression.Lambda<Func<IEnumerator<string>, string>>
              (
                methodCall, 
                enumeratorParameter
              );

    var lstConstant = "1,2,3,4,".Split(',');
    e.Compile()(lstConstant.ToList().GetEnumerator());
}

class SampleExpression
{
    public static string SampleEnum(IEnumerator<string> ien)
    {
        while (ien.MoveNext())
        {
            Console.WriteLine(ien.Current);
        }

        return "Done!";
    }
}