Come faccio a chiamare metodi con variabili di riferimento con Expression Trees

.net c# expression-trees

Domanda

Sto cercando di capire come creare un'espressione che chiama un metodo che ha un parametro di riferimento.

Lasciatemi spiegare la mia domanda con un esempio semplice (ma artificiale). Considera il metodo:

    public static int TwiceTheInput(int x)
    {
        return x*2;
    }

Posso creare un'espressione per chiamare il metodo sopra facendo qualcosa del tipo:

    {
        var inputVar = Expression.Variable(typeof (int), "input");
        var blockExp =
            Expression.Block(
                    new[] {inputVar}
                    , Expression.Assign(inputVar, Expression.Constant(10))
                    , Expression.Assign(inputVar, Expression.Call(GetType().GetMethod("TwiceTheInput", new[] { typeof(int) }), inputVar))
                    , inputVar
                    );
        var result = Expression.Lambda<Func<int>>(blockExp).Compile()();
    }

All'esecuzione, il "risultato" sopra dovrebbe finire con un valore di 20. Ora considera una versione di TwiceTheInput () che utilizza parametri di riferimento per riferimento:

    public static void TwiceTheInputByRef(ref int x)
    {
        x = x * 2;
    }

Come scrivere un albero delle espressioni simile per chiamare TwiceTheInputByRef () e passare gli argomenti in base ad esso?

Soluzione: (Grazie a Cicada). Uso:

Type.MakeByRefType()

Ecco un segmento di codice per generare l'albero delle espressioni:

        {
        var inputVar = Expression.Variable(typeof(int), "input");
        var blockExp =
            Expression.Block(
                    new[] { inputVar }
                    , Expression.Assign(inputVar, Expression.Constant(10))
                    , Expression.Call(GetType().GetMethod("TwiceTheInputByRef", new[] { typeof(int).MakeByRefType() }), inputVar)
                    , inputVar
                    );
        var result = Expression.Lambda<Func<int>>(blockExp).Compile()();
    }

Risposta accettata

Non è necessario modificare molto, basta rimuovere l' Assign e modificare typeof(int) in typeof(int).MakeByRefType() .

var blockExp = Expression.Block(
    new[] { inputVar }
    , Expression.Assign(inputVar, Expression.Constant(10))
    , Expression.Call(
       typeof(Program).GetMethod( 
           "TwiceTheInputByRef", new [] { typeof(int).MakeByRefType() }),
       inputVar)
    , inputVar
);


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é