无法将 IEnumerable<string> 作为 Expression.Call 中的参数传递

Unable to pass IEnumerable<string> as parameter in Expression.Call

这是我的 class:

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());
    }

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

Expression of type 'System.Linq.Expressions.TypedConstantExpression' cannot be used for parameter of type 'System.Collections.Generic.IEnumerator1[System.String]' of method 'Void Enum(System.Collections.Generic.IEnumerator1[System.String])'

请帮忙。

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

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

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

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!";
    }
}