2012-02-08 16 views
16

¿Es posible hacer eso en C# 3 o 4? Tal vez con un poco de reflexión?Ejecutar un método antes de todos los métodos de una clase

class Magic 
{ 

    [RunBeforeAll] 
    public void BaseMethod() 
    { 
    } 

    //runs BaseMethod before being executed 
    public void Method1() 
    { 
    } 

    //runs BaseMethod before being executed 
    public void Method2() 
    { 
    } 
} 

EDITAR

Hay una solución alternativa para esto, hacer Magic un producto único y poner su código en el captador de la instancia estática. Eso es lo que hice:

public class Magic 
{ 

    private static Magic magic = new Magic(); 
    public static Magic Instance 
    { 
     get 
     { 
      magic.BaseMethod(); 
      return magic; 
     } 
    } 

    public void BaseMethod() 
    { 
    } 

    //runs BaseMethod before being executed 
    public void Method1() 
    { 
    } 

    //runs BaseMethod before being executed 
    public void Method2() 
    { 
    } 
} 
+4

¿Qué tal un constructor? – JConstantine

+1

Usar un constructor no es una solución, porque si tuviera que ejecutar, digamos, dos métodos de una instancia, solo obtendría el método base para ejecutarlo una vez. También muy inadecuado para instancias estáticas. –

+0

Puede hacer esto usando 'dynamic' e implementando [' IDynamicMetaObjectProvider'] (http://msdn.microsoft.com/en-us/library/system.dynamic.idynamicmetaobjectprovider.aspx). Esto le permitirá ejecutar su propio código durante el enlace, lo que sucede antes de que se ejecute un método. Nota: esta sugerencia se proporciona como una curiosidad. En realidad, no es una buena manera de resolver su problema. – Brian

Respuesta

7

Hay una solución alternativa para este , haz de Magic un singleton y pon tu código en el captador de la instancia estática. Eso fue lo que hice.

public class Magic{ 

private static Magic magic; 
public static Magic Instance{ 
    get 
    { 
    BaseMethod(); 
    return magic; 
    } 
} 

public void BaseMethod(){ 
} 

//runs BaseMethod before being executed 
public void Method1(){ 
} 

//runs BaseMethod before being executed 
public void Method2(){ 
} 
} 
+0

esto parece interesante pero no funcionará. el campo privado no se inicia. Si explicas cómo iniciar el campo mágico, esto puede funcionar. – hakan

+0

Podría hacer un inicio perezoso, es decir, verificar si es nulo antes de acceder (generalmente solo la primera vez). Si es así, ejecútalo. – CBinet

8

No puede hacer esto automáticamente en C# - probablemente debería estar mirando AOP, p. con PostSharp.

+0

Tengo algunas dudas sobre AOP como solución para esto, porque creo que OP quiere ejecutar un método antes de invocar un método y más tarde ya no utilizar el aspecto. ¿Tal vez algún indicador de instancia de clase como _Initialized_ y si es _true_, no hace nada en el aspecto? –

+0

@ MatíasFidemraizer: No lo creo, basado en un comentario posterior: "Usar un constructor no es una solución, porque si tuviera que ejecutar, digamos, dos métodos de una instancia, solo obtendría el método base para ejecutar una vez "- así que creo que el OP quiere que el método se ejecute en * cada * invocación. –

+0

¡Bien, entonces, PostSharp (o cualquier otro marco de AOP) es nuestra solución!Este comentario fue publicado después de mis dudas. Y, creo que esta es la respuesta correcta, porque _IL weaving_ es mejor que el proxy para este caso. –

0

sólo para hacer una cosa clara la razón por la siguiente implementación no funcionará:

public class Magic{ 

private static Magic magic = new Magic(); 
public static Magic Instance{ 
    get 
    { 
    magic.BaseMethod(); 
    return magic; 
    } 
} 

public void BaseMethod(){ 
} 

//runs BaseMethod before being executed 
public void Method1(){ 
} 

//runs BaseMethod before being executed 
public void Method2(){ 
} 
} 

en el caso lo que desea es mantener un objeto Magic, el método será llamado al azar:

Magic m = Magic.Instance; //this will trigger unwanted call on BaseMethod 

y también si uno querrá llamar a la BaseMethod, se llama dos veces:

Magic.Instance.BaseMethod(); //two calls of the BaseMethod 

que por supuesto tiene una solución, para volver objetos no deseados utilizando GET:

var unused = Magic.Instance; 

Sólo para resumir: Esto no es posible (al menos por ahora) en C#.

Cuestiones relacionadas