.NET: determina el tipo de clase “this” en su método estático

En un método no estático podría usar this.GetType() y devolvería Type . ¿Cómo puedo obtener el mismo Type en un método estático? Por supuesto, no puedo simplemente escribir typeof(ThisTypeName) porque ThisTypeName se conoce solo en tiempo de ejecución. ¡Gracias!

Si está buscando un liner que sea equivalente a esto. this.GetType() para métodos estáticos, intente lo siguiente.

 Type t = MethodBase.GetCurrentMethod().DeclaringType 

Aunque es probable que esto sea mucho más costoso que el simple uso de typeof(TheTypeName) .

Hay algo que las otras respuestas no han aclarado del todo, y que es relevante para su idea de que el tipo solo está disponible en el momento de la ejecución.

Si usa un tipo derivado para ejecutar un miembro estático, el nombre del tipo real se omite en el binario. Entonces, por ejemplo, comstack este código:

 UnicodeEncoding.GetEncoding(0); 

Ahora usa ildasm en él … verás que la llamada se emite así:

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

El comstackdor resolvió la llamada a Encoding.GetEncoding : no queda ningún rastro de UnicodeEncoding . Eso hace que tu idea del “tipo actual” no tenga sentido, me temo.

Otra solución es usar un tipo autoreferente

 //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); } } 

Luego, en la clase que lo hereda, hago un tipo de auto referenciado:

 public class Child: Parent { } 

Ahora el tipo de llamada typeof (TSelfReferenceType) dentro de Parent obtendrá y devolverá el tipo de la persona que llama sin necesidad de una instancia.

 Child.GetType(); 

-Robar

No puede usar this en un método estático, por lo que no es posible directamente. Sin embargo, si necesita el tipo de algún objeto, simplemente llame a GetType y GetType en un parámetro que debe pasar, por ejemplo:

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

Esto parece un diseño pobre, sin embargo. ¿Estás seguro de que realmente necesitas obtener el tipo de instancia propia dentro de su propio método estático? Eso parece un poco extraño. ¿Por qué no usar un método de instancia?

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

No entiendo por qué no puedes usar typeof (ThisTypeName). Si este es un tipo no genérico, entonces esto debería funcionar:

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

Si es un tipo genérico, entonces:

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

¿Me estoy perdiendo algo obvio aquí?

Cuando su miembro es estático, siempre sabrá de qué tipo es parte en tiempo de ejecución. En este caso:

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

No puede llamar (editar: aparentemente, puede ver el comentario a continuación, pero aún estaría llamando a A):

 B.GetInt(); 

porque el miembro es estático, no juega parte de los escenarios de herencia. Ergo, siempre sabes que el tipo es A.

Para mis propósitos, me gusta la idea de @T-moty. Aunque utilicé la información del “tipo de autorreferencia” durante años, hacer referencia a la clase base es más difícil de hacer más adelante.

Por ejemplo (usando el ejemplo de @Rob Leclerc de arriba):

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

Trabajar con este patrón puede ser desafiante, por ejemplo; ¿cómo se devuelve la clase base de una llamada a función?

 public Parent GetParent() {} 

O cuando el tipo de fundición?

 var c = (Parent) GetSomeParent(); 

Por lo tanto, trato de evitarlo cuando puedo, y usarlo cuando debo. Si debe hacerlo, le sugiero que siga este patrón:

 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) {} } 

Ahora puede (más) trabajar fácilmente con la BaseClass . Sin embargo, hay momentos, como mi situación actual, donde no es necesario exponer la clase derivada, desde dentro de la clase base, y usar la sugerencia de @M-moty podría ser el enfoque correcto.

Sin embargo, usar el código de @M-moty solo funciona siempre que la clase base no contenga ningún constructor de instancia en la stack de llamadas. Lamentablemente, mis clases base usan constructores de instancias.

Por lo tanto, aquí está mi método de extensión que tiene en cuenta los constructores de ‘instancia’ de la clase 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; } } 

EDITAR Este método funcionará solo cuando implemente archivos PDB con el ejecutable / biblioteca, como me señaló markmnl .

De lo contrario, será un gran problema para detectar: ​​funciona bien en el desarrollo, pero tal vez no en la producción.


Método de utilidad, simplemente llame al método cuando lo necesite, desde cualquier lugar de su código:

 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; }