Impossible de passer IEnumerable comme paramètre dans Expression.Call

c# expression-trees lambda linq

Question

Ceci est ma classe:

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

Voici comment j'essaie d'invoquer la méthode 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());
    }

J'obtiens l'erreur suivante dans la ligne qui tente de créer l'expression d'appel de méthode:

L'expression de type 'System.Linq.Expressions.TypedConstantExpression' ne peut pas être utilisée pour le paramètre de type 'System.Collections.Generic.IEnumerator 1[System.String]' of method 'Void Enum(System.Collections.Generic.IEnumerator 1 [System .Chaîne])'

S'il vous plaît aider.

Réponse acceptée

Vous semblez très confus. Il serait peut-être utile de regarder comment le compilateur C # générerait un arbre d’expression similaire. Dans tous les cas, vous avez commis quelques erreurs:

  • IEnumerable<T> n'est pas IEnumerator<T> . Ils ne sont pas interchangeables.
  • param2 est une expression de paramètre qui prend SampleExpression , alors que votre lambda attend réellement IEnumerator<string> .
  • ep est une expression constante d'une expression constante . Ce n'est pas ce que tu veux. Supprimez l' Expression.Constant externe.Constant.
  • De toute façon, l'argument lambda n'est pas réellement utilisé - vous pouvez simplement utiliser Func<string> au lieu de Func<IEnumerator<string>, string> .
  • Votre arbre d'expression n'a pas de valeur de retour, tandis que le lambda s'attend à renvoyer une string .

En supposant que vous vouliez un lambda qui prenne IEnumerator<string> et l'utilise pour appeler SampleExpression.SampleEnum , vous pourriez utiliser quelque chose comme ceci:

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



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi