In una delle mie librerie, Ho codice che restituisce un MethodInfo da un'espressione:Perché i differenti versioni di .net (o il compilatore) generano diversi alberi di espressione per la stessa espressione
public MethodInfo GetMethod(Expression expression)
{
var lambdaExpression = (LambdaExpression)expression;
var unaryExpression = (UnaryExpression)lambdaExpression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
return (MethodInfo)methodInfoExpression.Value;
}
Ho avuto un serie di funzioni di supporto per abilitare le chiamate come la seguente:
public MethodInfo Func<T, R, A1>(Expression<Func<T, Func<A1, R>>> expression)
{
return GetMethod(expression);
}
Ciò consentirebbe la seguente sintassi:
var methodInfo = Func<TestClass, bool, string>(x => x.AnInstanceMethodThatTakesAStringAndReturnsABool);
Questo ha funzionato benissimo, fino a quando non ho aggiornato la libreria su .Net 4.6.1 e l'ultimo compilatore C#.
Nella versione precedente di .NET, l'espressione sarebbe della forma:
{x => Convert(CreateDelegate(System.Func`2[System.String, System.Boolean], x, Boolean AnInstanceMethodThatTakesAStringAndReturnsABool(System.String)))}
Da qui il mio codice sarà per la methodInfoExpression come ultimo argomento del methodCallExpression.
Ora, in .Net 4.6.1 (ultima compilatore C#), il compilatore sembra essere la produzione di espressione di una forma diversa:
{x => Convert(Boolean AnInstanceMethodThatTakesAStringAndReturnsABool(System.String).CreateDelegate(System.Func`2[System.String, System.Boolean], x))}
mie pause di codici attuali, perché l'ultimo argomento non è un ConstantExpression . Guardando la cosa - soluzione semplice, basta cambiare a
var methodInfoExpression = (ConstantExpression)methodCallExpression.Object;
Ovviamente, la funzione GetMethod è piuttosto fragile e soggetto a modifiche al modo in cui il compilatore genera espressioni. Sono curioso di sapere la ragione del cambiamento e di come posso rifattare GetMethod in modo che sia più resistente all'albero delle espressioni generato dal compilatore.
Si dovrebbe davvero pubblicare il codice di esempio che compila quando si fornisce un esempio. E se vuoi aiutare a scrivere il metodo in modo più efficace, dovresti effettivamente descrivere ciò che deve fare, piuttosto che mostrare solo la versione non funzionante di esso. – Servy