2009-12-08 2 views
16

Come posso ottenere i valori di parms (in un ciclo usando la riflessione). Nella domanda precedente, qualcuno mi ha mostrato come passare in rassegna i parms usando la riflessione.C# Ottenere il valore di parms usando la riflessione

static void Main(string[] args) 
{ 
    ManyParms("a","b","c",10,20,true,"end"); 
    Console.ReadLine(); 
} 

static void ManyParms(string a, string b, string c, int d, short e, bool f, string g) 
{ 
    var parameters = MethodBase.GetCurrentMethod().GetParameters(); 
    foreach (ParameterInfo parameter in parameters) 
    { 
     string parmName = parameter.Name; 
     Console.WriteLine(parmName); 
     //Following idea required an object first 
     //Type t = this.GetType(); 
     //t.GetField(parmName).GetValue(theObject)); 

    } 
} 

Se è necessario sapere perché io voglio fare questo, si prega di vedere qui: .NET Reflection of all method parameters


Grazie tutti - sembra che in Python, Perl, PHP questo sarebbe stato facile.
Anche se potrebbe non essere un riflesso, se utilizzo il reflection per ottenere il nome del campo, sembra che ci sarebbe un modo semplice e dinamico per ottenere il valore in base al nome. Non ho ancora provato le soluzioni AOP (Aspect Oriented Programming). Questa è una di quelle cose che se non posso farlo in un'ora o due, probabilmente non lo farò.

+0

Forse qualcosa potrebbe essere fatto controllando attraverso la riflessione della macchina statale che viene generato quando si utilizza un IEnumerable? Solo un'idea non saprei come realizzarmi :-) (Commentando qui a causa di una domanda doppia oggi) – Jbjstam

risposta

19

Non è possibile, fondamentalmente - almeno non senza aggancio nello debugger/profiling API.

In teoria ci potrebbero essere un certo senso dei valori dei parametri StackFrame classe di esporre, ma non è così - e ho il sospetto che, per farlo, che avrebbe dovuto rimuovere diversi ottimizzazioni.

4

Non è possibile tramite riflessione, e non si dovrebbe comunque farlo.

Se è necessario questo tipo di funzionalità, utilizzare un proxy, ad es. tramite un'implementazione RealProxy che intercetta la chiamata per te. Quindi, è possibile controllare e modificare qualsiasi parametro prima che venga effettuata la chiamata effettiva (o addirittura non effettuare la chiamata originale, dipende solo da te).

+0

Vedrò questo se avrò più tempo. Se vedi il mio post di riferimento sopra, però, sto usando Microsoft Host Integration Server e in particolare HIP - e non sono sicuro di come il proxy potrebbe giocare con quei ragazzi. – NealWalters

4

Non puoi farlo. Reflection funziona su meta-dati incorporati durante la compilazione e in quel momento i valori dei parametri non sono noti.

+4

Ma è possibile utilizzare la riflessione per ottenere valori di proprietà negli oggetti, che non sono noti al momento della compilazione. – NealWalters

4

Avete considerato l'utilizzo di AOP, come PostSharp?

È possibile accedere ai valori degli argomenti prima dell'esecuzione del metodo e il codice verrà quindi ridotto a una classe di attributi riutilizzabile e un attributo applicato ai metodi che devono avere questo controllo.

2

Non è possibile ottenere il valore dei parametri del metodo utilizzando la riflessione. Perché reflection restituisce le informazioni sui metadati. Se desideri ottenere il valore di un campo o una proprietà specifici, devi utilizzare anche un'istanza (come già sai).

Esistono diversi modi per ottenere il valore di un parametro utilizzando il plumbing interno del framework .NET, ovvero API profiler e API debugger.

È possibile utilizzare AOP per ciò che si sta tentando di fare, esiste un progetto Codeplex chiamato CThru che potrebbe essere d'aiuto: utilizzando CThru è possibile intercettare il metodo quando viene chiamato e ottenere i parametri con cui è stato chiamato.

32

Puoi aggirarlo creando un tipo anonimo all'interno del tuo metodo e sfruttando gli inizializzatori di proiezione. È quindi possibile interrogare le proprietà del tipo anonimo utilizzando la reflection. Per esempio:

static void ManyParms(
    string a, string b, string c, int d, short e, bool f, string g) 
{ 
    var hack = new { a, b, c, d, e, f, g }; 

    foreach (PropertyInfo pi in hack.GetType().GetProperties()) 
    { 
     Console.WriteLine("{0}: {1}", pi.Name, pi.GetValue(hack, null)); 
    } 
} 
+5

Ciò richiede di cambiare il contenuto del metodo. Se hai intenzione di farlo, puoi semplicemente riportare i valori comunque. Questa sintassi rende leggermente più semplice farlo, ma dubito che possa davvero aiutare l'OP. –

+0

@Jon: hai ragione, ovviamente, ma questo è * molto * meno tipografico rispetto a farlo manualmente e perché non ci sono più righe con hardcoded come 'Console.WriteLine (" a: "+ a)' etc , c'è molto meno margine di errore. – LukeH

+2

È un brillante workarround – Serge