.NET: Determina il tipo di “questa” class nel suo metodo statico

In un metodo non statico potrei usare this.GetType() e restituirebbe il Type . Come posso ottenere lo stesso Type in un metodo statico? Naturalmente, non posso semplicemente scrivere typeof(ThisTypeName) perché ThisTypeName è noto solo in runtime. Grazie!

Se stai cercando un liner equivalente a this.GetType() per i metodi statici, prova quanto segue.

 Type t = MethodBase.GetCurrentMethod().DeclaringType 

Anche se questo è probabilmente molto più costoso rispetto all’utilizzo di typeof(TheTypeName) .

C’è qualcosa che le altre risposte non hanno ancora chiarito e che è rilevante per la tua idea del tipo che è disponibile solo al momento dell’esecuzione.

Se si utilizza un tipo derivato per eseguire un membro statico, il nome del tipo reale viene omesso nel file binario. Quindi, ad esempio, compila questo codice:

 UnicodeEncoding.GetEncoding(0); 

Ora usa ildasm su di esso … vedrai che la chiamata viene emessa in questo modo:

 IL_0002: call class [mscorlib]System.Text.Encoding [mscorlib]System.Text.Encoding::GetEncoding(int32) 

Il compilatore ha risolto la chiamata a Encoding.GetEncoding – non rimane traccia di UnicodeEncoding . Ho paura che la tua idea di “tipo attuale” sia priva di senso.

Un’altra soluzione è usare un tipo selfreferecing

 //My base class //I add a type to my base class use that in the static method to check the type of the caller. public class Parent { public static Type GetType() { return typeof(TSelfReferenceType); } } 

Quindi nella class che lo eredita, faccio un tipo di auto-referenziamento:

 public class Child: Parent { } 

Ora il tipo di chiamata typeof (TSelfReferenceType) all’interno di Parent otterrà e restituirà il Tipo del chiamante senza bisogno di un’istanza.

 Child.GetType(); 

-Rapinare

Non è ansible utilizzarlo in un metodo statico, quindi non è ansible direttamente. Tuttavia, se hai bisogno del tipo di qualche object, chiama semplicemente GetType e rendi this istanza un parametro che devi passare, ad esempio:

 public class Car { public static void Drive(Car c) { Console.WriteLine("Driving a {0}", c.GetType()); } } 

Questo sembra un design scadente, però. Sei sicuro di aver davvero bisogno di ottenere il tipo di istanza stessa all’interno del proprio metodo statico? Sembra un po ‘bizzarro. Perché non usare solo un metodo di istanza?

 public class Car { public void Drive() { // Remove parameter; doesn't need to be static. Console.WriteLine("Driving a {0}", this.GetType()); } } 

Non capisco perché non puoi usare typeof (ThisTypeName). Se questo è un tipo non generico, allora dovrebbe funzionare:

 class Foo { static void Method1 () { Type t = typeof (Foo); // Can just hard code this } } 

Se è un tipo generico, quindi:

 class Foo { static void Method1 () { Type t = typeof (Foo); } } 

Mi sto perdendo qualcosa di ovvio qui?

Quando il tuo membro è statico, saprai sempre di che tipo fa parte in fase di runtime. In questo caso:

 class A { public static int GetInt(){} } class B : A {} 

Non puoi chiamare (modifica: apparentemente, puoi, vedi il commento qui sotto, ma staresti ancora chiamando in A):

 B.GetInt(); 

poiché il membro è statico, non gioca parte negli scenari di ereditarietà. Ergo, tu sai sempre che il tipo è A.

Per i miei scopi, mi piace l’idea di @ T-moty. Anche se per anni ho usato informazioni di tipo “autoreferenziale”, fare riferimento alla class base è più difficile da fare in seguito.

Ad esempio (usando l’esempio @Rob Leclerc dall’alto):

 public class ChildA: Parent { } public class ChildB: Parent { } 

Lavorare con questo modello può essere difficile, ad esempio; come si restituisce la class base da una chiamata di funzione?

 public Parent< ???> GetParent() {} 

O quando scrivi il casting?

 var c = (Parent< ???>) GetSomeParent(); 

Quindi, cerco di evitarlo quando posso e usarlo quando devo. Se devi, ti suggerisco di seguire questo schema:

 class BaseClass { // All non-derived class methods goes here... // For example: public int Id { get; private set; } public string Name { get; private set; } public void Run() {} } class BaseClass : BaseClass { // All derived class methods goes here... // For example: public TSelfReferenceType Foo() {} public void Bar(TSelfRefenceType obj) {} } 

Ora puoi (più) lavorare facilmente con BaseClass . Tuttavia, ci sono momentjs, come la mia situazione attuale, in cui l’esposizione della class derivata, all’interno della class base, non è necessaria e l’utilizzo del suggerimento di @ M-moty potrebbe essere l’approccio giusto.

Tuttavia, usando il codice di @ M-moty funziona solo finché la class base non contiene costruttori di istanze nello stack di chiamate. Sfortunatamente le mie classi di base usano i costruttori di istanze.

Pertanto, ecco il mio metodo di estensione che tiene conto dei costruttori di ‘istanza’ della class base:

 public static class TypeExtensions { public static Type GetDrivedType(this Type type, int maxSearchDepth = 10) { if (maxSearchDepth < 0) throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0."); const int skipFrames = 2; // Skip the call to self, skip the call to the static Ctor. var stack = new StackTrace(); var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount); var frame = skipFrames; // Skip all the base class 'instance' ctor calls. // while (frame < maxCount) { var method = stack.GetFrame(frame).GetMethod(); var declaringType = method.DeclaringType; if (type.IsAssignableFrom(declaringType)) return declaringType; frame++; } return null; } } 

MODIFICA Questo metodo funziona solo quando si distribuiscono file PDB con l’eseguibile / libreria, come indicato da Markmnl .

Altrimenti sarà un grosso problema da rilevare: funziona bene nello sviluppo, ma forse non in produzione.


Metodo di utilità, chiama semplicemente il metodo quando ti serve, da ogni luogo del tuo codice:

 public static Type GetType() { var stack = new System.Diagnostics.StackTrace(); if (stack.FrameCount < 2) return null; return (stack.GetFrame(1).GetMethod() as System.Reflection.MethodInfo).DeclaringType; }