Come passare la variabile argomento runtime in Expression.Call?

argumentexception c# expression-trees

Domanda

Mi manca qualcosa di banale qui. Dì che ho un metodo come questo:

abstract class C
{
    public static void M(Type t, params int[] i)
    {

    }
}

Sto imparando gli alberi delle espressioni e ho bisogno di creare un delegato che chiami questo metodo con alcuni argomenti predefiniti . Il problema è che non so scegliere il sovraccarico corretto e passare argomenti di Expression.Call .

Voglio raggiungere questo:

//I have other overloads for M, hence I need to specify the type of arugments
var methodInfo = typeof(C).GetMethod("M", new Type[] { typeof(Type), typeof(int[]) });

//this is the first argument to method M, not sure if I have chosen the right expression
var typeArgumentExp = Expression.Parameter(someType);

var intArrayArgumentExp = Enumerable.Repeat(Expression.Constant(0), 3);

var combinedArgumentsExp = new Expression[] { typeArgumentExp }.Concat(intArrayArgumentExp);
var call = Expression.Call(methodInfo, combinedArgumentsExp);

Alla riga Expression.Call ottengo:

Si è verificata un'eccezione non gestita di tipo "System.ArgumentException" in System.Core.dll

Ulteriori informazioni: numero errato di argomenti forniti per la chiamata al metodo "Void M (System.Type, Int32 [])"

Dove ho sbagliato?

Risposta accettata

L'ho risolto in questo modo (mostrato qui Calling (oggetto params []) con Expression [] ):

//I have other overloads for M, hence I need to specify the type of arugments
var methodInfo = typeof(C).GetMethod("M", new Type[] { typeof(Type), typeof(int[]) });

//I fixed this issue where the first argument should be typeof(Type)
var typeArgumentExp = Expression.Parameter(typeof(Type));

var intArrayArgumentExp = Expression.NewArrayInit(typeof(int), Enumerable.Repeat(Expression.Constant(0), 3));

var combinedArgumentsExp = new Expression[] { typeArgumentExp }.Concat(intArrayArgumentExp);
var call = Expression.Call(methodInfo, combinedArgumentsExp);

Expression.NewArrayInit fa il trucco. Grazie hvd per la sua direzione.


Risposta popolare

La parola chiave params non esegue nulla in fase di runtime. Quando chiami CM(t, 1, 2, 3) , il compilatore lo trasforma in CM(t, new int[] { 1, 2, 3 }) . In questo caso, stai eseguendo parti del lavoro del compilatore e questa è una trasformazione che diventa responsabilità dell'utente. Dovresti creare esplicitamente la matrice e chiamare CM con esattamente due argomenti.



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é