2010-03-26 13 views
12

¿Cómo puedo obtener el ConstructorInfo para un constructor estático?¿Cómo invoco un constructor estático con reflejo?

public class MyClass 
{ 
    public static int SomeValue; 

    static MyClass() 
    { 
     SomeValue = 23; 
    } 
} 

He intentado lo siguiente y no ....

Type myClass = typeof (MyClass); 

// throws exception 
myClass.TypeInitializer.Invoke(null);  

// returns null (also tried deleting BindingFlags.Public 
ConstructorInfo ci = myClass.GetConstructor(BindingFlags.Static|BindingFlags.Public, System.Type.DefaultBinder, System.Type.EmptyTypes, null); 

// returns empty array 
ConstructorInfo[] clutchingAtStraws = myClass.GetConstructors(BindingFlags.Static| BindingFlags.Public); 

Respuesta

27

Uso myClass.TypeInitializer.Invoke(null, null).

Acabo de probar esto y funcionó bien.

Recomiendo encarecidamente que no lo haga haga esto, sin embargo, viola un tipo que espera que el constructor estático solo se ejecute una vez. Use RuntimeHelpers.RunClassConstructor según Oliver's answer si solo está tratando de asegurarse de que se inicialice una clase.

+0

+1 gracias Jon! La respuesta parece tan obvia ahora * sonrisa * –

+0

Necesitaba acceder a ella para poder [aplicarle un aspecto usando PostSharp] (http://www.sharpcrafters.com/). Supongo que todavía es un caso de uso válido. –

+2

Downvoted, solo porque la siguiente respuesta es (al menos en teoría) mucho más segura. p.s. ... Maldita sea, acabo de rechazar la respuesta de Jon Skeet. ¿No soy valiente? –

2

¿Probaste también BindingFlags.Private?

Tenga en cuenta que al constructor estático se le garantiza el llamado antes de cualquier llamada a cualquier otra instancia o método estático de esta clase, y se garantiza que sea seguro para hilos y se llame exactamente una vez.

Si desea llamar explícitamente con la reflexión que podría hacer un montón de daño ..

7

A pesar de que es posible, puede que no sea una buena idea hacer eso. Sin embargo, si accede a cualquier miembro de la clase, el tiempo de ejecución invocará automáticamente el constructor estático. Por ejemplo:

// Read the field 'SomeValue', so that the runtime invokes static ctor 
Type myClass = typeof(MyClass); 
myClass.GetField("SomeValue").GetValue(null); 

Desde el acceso a un campo de la clase no puede causar ningún efecto secundario (aparte de la inicialización de la clase y llamar al constructor estática), esto debería ser una forma relativamente segura de hacer esto en general (Sin embargo, seguirá funcionando solo para clases con algún campo estático). Esto tiene la ventaja de que garantiza que se invocará el constructor de tipo como máximo una vez, que es bastante importante.

+1

Extraño, pero llegué a esta pregunta solo porque el campo de solo lectura que necesitaba no se inició en el momento en que lo accedía. Puedo apostar que la mayoría de la gente está aquí por la misma razón. –

23

También hay System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(RuntimeTypeHandle type), que garantiza, además, que el constructor estático sólo se le llama una vez, sin importar cuántas veces se llama el método:

Type myClass = typeof(MyClass); 
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(myClass.TypeHandle); 

Reference

+5

Esta es la respuesta correcta real. Eso me salvó la vida de una muerte segura !!!! – Xtro

Cuestiones relacionadas