Question

Je fais une analyse de l'utilisateur à partir de l'utilisateur, et je dois ici analyser des arguments qui devraient être de certains types.

Au moment de l'analyse, je ne sais pas de quel type d'argument devrait être, mais cela pourrait être évalué à n'importe quel type. Donc, j'ai décidé de les stocker temporairement dans un tableau d'objets. Mais quand j'essaie de faire quelque chose comme ça:

NewArrayExpression returnValue = Expression.NewArrayInit(typeof(object), expressionList);

Je reçois une exception suivante: une expression de type 'system.int32' ne peut pas être utilisée pour initialiser un tableau de type 'system.Object'.

C'est-à-dire que je suppose, car aucune boxe implicite ne se passe. Alors je le baisse moi-même:

expressionList.Add(Expression.TypeAs(expression, typeof(object))); or
expressionList.Add(Expression.Convert(expression, typeof(object)));

jusqu'à présent si bon: j'ai eu la liste d'objets de différents types dans un tableau.

Mais, lorsque je reçois enfin le type souhaité, j'essaie de convertir toutes les valeurs de la matrice supérieure à ce type (disons que le type étant d'usualy AT) Je le convertit:

Expression.Convert(expr, typeof(int)); or
Expression.Unbox(expr, typeof(int));

Ceci est la vue de débogage des deux commandes lorsque Expr est actuellement une chaîne "AAAAA":

(System.Int32)((System.Object)"aaaaa")

Maintenant, voici mon problème: cela ne jettera pas une exception. Mais ce sera quand l'expression est finalement compilée. Je veux dire, la chaîne n'est pas un int.

Peut-être que cela ne devrait pas vraiment jeter une exception, je ne sais pas. Mais cela ne fonctionne pas pour moi.

Y a-t-il un remède contre cela?

edit: Le code ressemble à ceci:

static Expression InArguments(ParameterExpression pe, string[] arguments)
{
    List<Expression> listaExpr = new List<Expression>();
    foreach (string s in arguments)
    {
        Expression expression = Complete(pe, s); // evaluate argument
        // listaExpr.Add(Expression.Convert(expression, typeof(object)));
    }
    return Expression.NewArrayInit(typeof(object), listaExpr);
}

Était-ce utile?

La solution

Il me semble que vous connaissez le type, c'est juste que vous le calculez trop tard.Si vous pouviez changer cela, cela résoudrait votre problème.La méthode ressemblerait alors à ceci:

static Expression InArguments(
    ParameterExpression pe, string[] arguments, Type itemType)
{
    List<Expression> listaExpr = new List<Expression>();
    foreach (string s in arguments)
    {
        Expression expression = Complete(pe, s, itemType); // evaluate argument
        listaExpr.Add(expression, typeof(object));
    }
    return Expression.NewArrayInit(itemType, listaExpr);
}

Et le code qui appelle cela pourrait ressembler à ceci:

Expression inProperty = InProperty(…);
Expression inArguments = InArguments(pe, arguments, inProperty.Type);

Expression result = Expression.Call(containsMethod, inArguments, inProperty);

Autres conseils

@svick

Ouais, c'était mon problème.Tout mon système a été configuré pour résoudre les opérandes gauche et droit de manière indépendante, puis vérifiez la convertibilité entre elles.Donc, je voulais que mon opérande de droit d'opérande de l'opérateur retourne une expression de la matrice d'objet afin que je puisse tester chacun des objets pour la convertibilité, mais cela me semble que une fois que je les convertis en objet, ils sont convertis sur n'importe quoi ???.

Alors, j'ai décidé de retourner l'expression suivante de mon opérande droit:

    static Expression InArguments(ParameterExpression pe, string arguments)
    {
        string substr = arguments.Substring(1, arguments.Length - 2);
        string[] arr = substr.Split(',');
        return Expression.Constant(arr, typeof(string[]));
    }

et ensuite plus tard:

    static Expression InOperator(Expression left, Expression right, ParameterExpression pe)
    {
        Expression finalexpr = null;

        // this solved my problem.
        string[] args = Expression.Lambda<Func<string[]>>(right).Compile()();

        foreach (string s in args)
        {
            Expression converted = null;                

            try
            {
                Expression expr = Complete(pe, s);
                converted = Expression.Convert(expr, (left as Expression).Type);
            }
            catch
            {
                throw;
            }

            if (finalexpr == null) finalexpr = Expression.Constant(false);
            finalexpr = Expression.OrElse(finalexpr, Expression.Equal(left, converted));
        }

        return finalexpr;
    }

J'ai préparé mes arguments au point où je peux faire référence au type d'opérande gauche, à l'intérieur d'une expression constante de chaîne [], puis de le compiler pour récupérer mes arguments de chaîne.

Mais toujours, j'aurais aimé si je pouvais l'avancer dans une matrice d'objet ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top