Come istanziare e inizializzare un oggetto dinamico nell'albero delle espressioni?

.net c# dynamic expression-trees iqueryable

Domanda

Quando lavoriamo con IQuerayble<TItem> possiamo chiamare Select questo modo:

query.Select( item => new { A=item.Prop1, B=item.Prop2});

E il metodo Select prevede Expression<Func<TItem,TResult>>

Devo usare ExpandoObject invece della classe anonima ma tipizzata staticamente.

Se fosse possibile sembrerebbe:

query.Select( item => dynamic new ExpandoBoject { A=item.Prop1, B=item.Prop2});

Quindi voglio costruire l'albero delle espressioni Expression<Func<TItem,ExpandoObject>> dove le proprietà dell'oggetto sono inizializzate in modo simile a quello del tipo anonimo.
La funzionalità dinamica è necessaria solo per l'inizializzazione, quindi è ExpandoObject che Func restituisca ExpandoObject anziché dynamic .

Non riesco a trovare molta documentazione su Expression.Dynamic e sui relativi raccoglitori che dovrei usare.


Aggiornamento 1

Perché ho bisogno di tutte queste cose?
Perché voglio ottenere le chiavi primarie .
Voglio farlo per qualsiasi tipo di entità.

So come ottenere l'elenco delle proprietà che compongono PK, ma ora ho bisogno di fare una proiezione complessa dell'entità su EntityKey . Bene, potrebbe essere lo stesso equivalente di questa classe.

var keys = context.Set<TEntity>().Where(Expression<Func<TEntity,bool>).Select(Expression<Func<TEntity,EntityKey>>);

Come ho notato nei commenti, i lambda contenenti blocchi non possono essere convertiti in alberi di espressione, quindi non posso creare il dizionario e riempirlo semplicemente. Ora sto giocando con l'albero delle espressioni semanticamente vicino a questo codice:

var dict = new Dictionary<string,object>();
dict.Add("Prop1",value1);
dict.Add("Prop2",value2);
return dict

Ma dubito che EF possa analizzare l'espressione contenente blocchi. Devo verificare.
E sono curioso di sapere se funzionerà con oggetti dinamici ed Expression.MemberInit come funziona con oggetti statici.


Aggiornamento 2

Entity Framework non supporta la sintassi di inizializzazione del dizionario.
Getta NotSupportedException con il messaggio: Elenca solo gli elementi di inizializzazione con un singolo elemento sono supportati in LINQ su Entità.


Aggiornamento 3

EF non supporta anche le espressioni di blocco.
NotSupportedException con messaggio: espressione LINQ sconosciuta di tipo "Block".

Risposta popolare

Ora sto giocando con l'albero delle espressioni semanticamente vicino a questo codice:

var dict = new Dictionary<string,object>();
dict.Add("Prop1",value1);
dict.Add("Prop2",value2);
return dict;

Si può fare, perché si può scrivere che codice come come una singola espressione in questo modo:

new Dictionary<string, object>
{
    { "Prop1", value1 },
    { "Prop2", value2 }
};

Ed è possibile creare un albero di espressioni che contenga questa espressione (che EF dovrebbe essere in grado di gestire) in questo modo:

var addMethod = typeof(Dictionary<string, object>).GetMethod("Add");

var expression = Expression.Lambda<Func<Dictionary<string, object>>>(
    Expression.ListInit(
        Expression.New(typeof(Dictionary<string, object>)),
        Expression.ElementInit(
            addMethod,
            Expression.Constant("Prop1"),
            value1Expression),
        Expression.ElementInit(
            addMethod,
            Expression.Constant("Prop2"),
            value2Expression)),
    itemParameterExpression);


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é