L'espressione di tipo "System.Int64" non può essere utilizzata per il tipo restituito "System.Object"

.net c# expression-trees linq reflection

Domanda

Sto cercando di creare un'espressione del seguente modulo:

e => e.CreationDate;

CreationDate è di tipo long , tuttavia voglio che l'espressione restituisca un object .

Voglio utilizzare l' object come tipo restituito perché l'espressione è creata dinamicamente in fase di esecuzione in base a un parametro di query. Il parametro query specifica la proprietà per accedere nell'espressione, ad esempio:

> entities?order=creationDate
> entities?order=score

Come puoi vedere, posso ordinare in base a proprietà diverse con tipi diversi, quindi un object tipo return mi consentirà di creare l'espressione nel modo più generico possibile.

Il problema è che quando provo a creare l'espressione:

ParameterExpression entityParameter = Expression.Parameter(typeof(Entity), "e");
Expression propertyAccess = Expression.Property(entityParameter, property);
Expression<Func<Entity, object>> result = Expression.Lambda<Func<Entity, object>>(propertyAccess, entityParameter);

Ottengo la seguente eccezione:

L'espressione di tipo "System.Int64" non può essere utilizzata per il tipo restituito "System.Object"

È strano, perché per quanto ne so, tutti i tipi si estendono object (Sembra che il polimorfismo non sia ancora supportato dagli alberi di espressione).

Tuttavia, ho cercato sul web e sono incappato in questa domanda simile:

L'espressione di tipo "System.Int32" non può essere utilizzata per il tipo restituito "System.Object"

Seguendo la risposta di Jon Skeet , ho modificato la mia ultima riga per:

Expression<Func<Entity, object>> result = Expression.Lambda<Func<Entity, object>>(Expression.Convert(propertyAccess, typeof(object)), entityParameter);

Funziona bene, ma non genera l'espressione che voglio. Invece, genera qualcosa di simile a questo:

e => Convert(e.CreationDate)

Non riesco a utilizzare questa soluzione, perché in seguito nel programma viene generata un'eccezione se il corpo dell'espressione non è una MemberExpression (cioè un'operazione di accesso membro)

Ho continuato a cercare su Internet una risposta soddisfacente, ma non sono riuscito a trovarne.

Come posso ottenere e => e.CreationDate dove tipo di e => e.CreationDate è object ?

Risposta accettata

A seconda di come si utilizza il result è possibile crearlo dinamicamente con il tipo delegato Func<Entity, long> e digitarlo come 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);

Risposta popolare

Risposta breve: no, non è possibile. I tipi di valore devono essere raggruppati per essere visti come oggetti. Il compilatore lo fa per te normalmente, ma se costruisci il codice tu stesso (es. Alberi di espressione), devi specificarlo come una conversione esplicita, come la vedi nella risposta trovata. Se non è possibile utilizzarlo come LambdaExpression non generico, gestirò ulteriormente il caso di conversione in cui prevedi l'espressione MemberExpression oppure utilizzerai PropertyInfo e costruirò l'espressione Espressione solo nell'ultimo momento.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché