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

.net c# expression-trees linq reflection

Question

J'essaie de créer une expression de la forme suivante:

e => e.CreationDate;

CreationDate est de type long , mais je souhaite que l'expression renvoie plutôt un object .

Je souhaite utiliser object comme type de retour, car l'expression est générée de manière dynamique au moment de l'exécution, en fonction d'un paramètre de requête. Le paramètre query spécifie la propriété à laquelle accéder dans l'expression, telle que:

e => e.CreationDate;

Comme vous pouvez le constater, je peux classer par propriétés différentes avec différents types, de sorte qu'un object type retour me permettrait de générer l'expression aussi générique que possible.

Le problème est que lorsque j'essaie de créer l'expression:

e => e.CreationDate;

Je reçois l'exception suivante:

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

C'est étrange, car à ma connaissance, tous les types s'étendent de l' object (il semble que le polymorphisme ne soit pas encore pris en charge par les arbres d'expression).

Néanmoins, j'ai cherché sur le Web et suis tombé sur cette question similaire:

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

Suite à la réponse de Jon Skeet , j'ai modifié ma dernière ligne en:

e => e.CreationDate;

Cela fonctionne bien, mais ne génère pas l'expression que je veux. Au lieu de cela, il génère quelque chose comme ceci:

e => e.CreationDate;

Je ne peux pas utiliser cette solution car, plus tard dans le programme, une exception est levée si le corps de l'expression n'est pas une MemberExpression (c.-à-d. Une opération d'accès membre).

J'ai continué à chercher sur Internet une réponse satisfaisante, mais je n'en ai trouvé aucune.

Comment puis-je obtenir e => e.CreationDate où type de retour est object ?

Réponse acceptée

En fonction de votre utilisation du result vous pouvez le créer dynamiquement avec le type de délégué Func<Entity, long> et le saisir en tant LambdaExpression :

ParameterExpression entityParameter = Expression.Parameter(typeof(Entity), "e");
Expression propertyAccess = Expression.Property(entityParameter, property);
var funcType = typeof(Func<,>).MakeGenericType(typeof(Entity), property.PropertyType);
LambdaExpression result = Expression.Lambda(funcType, propertyAccess, entityParameter);

Réponse populaire

Réponse courte: non, ce n'est pas possible. Les types de valeur doivent être encadrés pour être vus comme des objets. Le compilateur le fait normalement pour vous, mais si vous construisez vous-même du code (par exemple, des arbres d’expression), vous devez le spécifier en tant que conversion explicite, comme vous le voyez dans la réponse trouvée. Si vous ne pouvez pas l'avoir en tant que LambdaExpression non générique, je traiterai le cas converti en plus de l'attente de MemberExpression, ou utiliserez PropertyInfo, et ne construira le orderby que dans le dernier moment.




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