60 votes

L'expression de type 'System.Int32' ne peut pas être utilisée pour le type de retour 'System.Object'

Je suis en train de produire un simple système de script qui sera utilisé pour imprimer des étiquettes. Je l'ai fait dans le passé avec la réflexion pas de problème, mais je suis maintenant en train de le faire avec les Lambda fonctions afin que je puisse mettre en cache les fonctions pour une réutilisation.

Le code que j'ai pour l'instant est comme suit...

public static string GetValue<T>(T source, string propertyPath) {

    try {

        Func<T, Object> func;

        Type type = typeof(T);
        ParameterExpression parameterExpression = Expression.Parameter(type, @"source");
        Expression expression = parameterExpression;
        foreach (string property in propertyPath.Split('.')) {
            PropertyInfo propertyInfo = type.GetProperty(property);
            expression = Expression.Property(expression, propertyInfo);
            type = propertyInfo.PropertyType;
        }

        func = Expression.Lambda<Func<T, Object>>(expression, parameterExpression).Compile();

        object value = func.Invoke(source);
        if (value == null)
            return string.Empty;
        return value.ToString();

    }
    catch {

        return propertyPath;

    }

}

Cela semble fonctionner dans certains cas, mais dans d'autres, il échoue. Le problème semble être dans ma tente pour renvoyer les valeurs comme des objets - indépendamment des types de données réels. Je suis en train de faire cela parce que je ne sais pas au moment de la compilation que le type de données, mais dans le long terme, j'ai seulement besoin d'une chaîne de caractères.

Je suis l'exception indiqué dans le titre de ce message à chaque fois que j'essaie d'accéder à une propriété de type Int32 - mais je reçois également pour les types Nullables et les autres. L'exception est levée lorsque j'essaie de compiler l'expression dans la fonction.

Quelqu'un peut-il suggérer comment je pourrais aller à ce sujet différemment, tout en conservant le Lambda de la fonctionnalité, de sorte que je peux mettre en cache les accesseurs?

123voto

Jon Skeet Points 692016

Avez-vous essayé d'utiliser Expression.Convert ? Cela va ajouter la conversion de boxe / levage / etc.

 Expression conversion = Expression.Convert(expression, typeof(object));
func = Expression.Lambda<Func<T, Object>>(conversion, parameterExpression).Compile();
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X