Obtenir le type de retour réel d'une expression > instance

c# expression-trees reflection

Question

J'ai une méthode qui accepte une instance Expression<Func<T, object>> . Je souhaite connaître le type de données réel renvoyé par une instance d'expression spécifique plutôt que par un object .

Je peux le faire fonctionner pour les références de propriété directes, donc si je passe l'expression x => x.IntegerProperty je peux obtenir une référence de type pour un entier. Cette approche nécessite la conversion en MemberExpression.

Cependant, je ne peux pas le faire fonctionner pour des expressions arbitraires. Par exemple, si l'expression est x => x.IntegerProperty.ToString() je souhaite obtenir une référence de type pour une chaîne. Je ne peux pas compiler ceci dans un MemberExpression, et si je me contente de le .Compile() et vérifie le type de retour, j'obtiens "object".

Comment puis-je consulter l'instance d'expression spécifique et dériver le type de retour réel?

Réponse acceptée

Quelque chose comme ça pourrait faire l'affaire. Cela ne couvre probablement pas toutes les possibilités, mais c'est un début.

public static Type GetObjectType<T>(Expression<Func<T, object>> expr)
{
    if ((expr.Body.NodeType == ExpressionType.Convert) ||
        (expr.Body.NodeType == ExpressionType.ConvertChecked))
    {
        var unary = expr.Body as UnaryExpression;
        if (unary != null)
            return unary.Operand.Type;
    }
    return expr.Body.Type;
}

Réponse populaire

Bien que ce ne soit pas impossible, cela est particulièrement difficile. Cela nécessiterait de parcourir l'arbre d'expression et de mettre en œuvre une logique potentiellement complexe. Par exemple, que voudriez-vous voir si je passais dans l'expression suivante?

Func<bool, object> expr = switch => switch ? 1 : "False";

Cette méthode peut renvoyer un int ou une string .

Maintenant, vous pourrez peut-être faire plus de progrès en déchargeant une partie de cette logique sur le compilateur. Vous pouvez modifier le paramètre de votre méthode de Func<T, object> à Func<T, TReturn> et utiliser typeof(TReturn) dans la méthode pour déterminer ce que le compilateur a décidé du type de retour de l'expression.

Bien sûr, dans le cas de mon exemple, vous travaillerez toujours contre un object . Mais, votre exemple de x => x.IntegerProperty.ToString() donnera string , ce qui est ce que vous recherchez.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow