Domanda

Ecco il contesto per la mia domanda:

Una tecnica comune è dichiarare il parametro di un metodo come espressione Lambda anziché come delegato. Questo è così che il metodo può esaminare l'espressione per fare cose interessanti come scoprire i nomi delle chiamate al metodo nel corpo dell'istanza delegata.

Il problema è che perdi alcune delle funzionalità di Intelli-sense di Resharper. Se il parametro del metodo fosse dichiarato come delegato, Resharper sarebbe d'aiuto quando scriveva la chiamata a questo metodo, chiedendoti di x = > sintassi x da fornire come valore dell'argomento a questo metodo.

Quindi ... tornando alla mia domanda, vorrei fare quanto segue:

    MethodThatTakesDelegate(s => s.Length);
}

private void MethodThatTakesDelegate(Func<string, object> func)
{
    //convert func into expression
    //Expression<Func<string, object>> expr = "code I need to write"

    MethodThatTakesExpression(expr);
}


private void MethodThatTakesExpression(Expression<Func<string, object>> expr)
{
    //code here to determine the name of the property called against string (ie the Length)
}
È stato utile?

Soluzione

Ovunque tu stia utilizzando il termine "espressione lambda" intendi veramente "albero delle espressioni".

Un'espressione lambda è il bit nel codice sorgente che è

parameters => code

per es.

x => x * 2

Gli alberi delle espressioni sono istanze del System.Linq .Expressions.Expression classe (o meglio, una delle classi derivate) che rappresentano il codice come dati.

Le espressioni lambda vengono convertite dal compilatore in o alberi delle espressioni (o meglio, codice che genera un albero delle espressioni in fase di esecuzione) o istanze delegate.

Puoi compilare un'istanza di LambdaExpression (che è una delle sottoclassi di Expression) in un delegato, ma non puoi fare il contrario.

In teoria potrebbe essere possibile scrivere un tale "decompilatore" basato sull'IL restituito da MethodBase.GetMethodBody in alcune situazioni, ma attualmente ci sono vari delegati che non possono essere rappresentati dagli alberi delle espressioni. Un albero delle espressioni rappresenta una espressione piuttosto che una istruzione o blocco di istruzioni - quindi non ci sono cicli, ramificazioni (tranne i condizionali), assegnazioni ecc. Credo che questo possa cambiare in .NET 4.0, anche se non mi aspetterei un passaggio di decompilazione da Microsoft a meno che non ci sia davvero un buon motivo per farlo.

Altri suggerimenti

Non credo che sia possibile ottenere ciò che desideri qui. Dai commenti nel codice sembra che tu stia tentando di acquisire il nome della proprietà che ha eseguito l'assegnazione in MethodThatTakesExpression. Ciò richiede un'espressione lambda dell'albero delle espressioni che acquisisca il contesto dell'accesso alla proprietà.

Al momento in cui passi un delegato in MethodThatTakesDelegate questo contesto è perso. I delegati memorizzano solo un indirizzo del metodo e non un contesto relativo alle informazioni sul metodo. Una volta effettuata questa conversione, non è possibile ripristinarla.

Un esempio del perché ciò non è possibile è che potrebbe non esserci nemmeno un metodo denominato che supporti un delegato. È possibile utilizzare ReflectionEmit per generare un metodo che non ha alcun nome ed esiste solo in memoria. È possibile però assegnarlo a un oggetto Func.

No, non è possibile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top