2008-10-10 31 views
5

Lo que estoy buscando es una forma de llamar a un método después de invocarlo pero antes de ingresarlo . Ejemplo:Hay una manera en .NET de llamar automáticamente a un método después de que se haya invocado otro método, pero antes de que se haya ingresado

public class Test { 

    public void Tracer (...) 
    { 
    } 

    public int SomeFunction(string str) 
    { 
    return 0; 
    } 

    public void TestFun() 
    { 
    SomeFunction(""); 
    } 

} 

En el ejemplo anterior me gustaría tener trazador() llamada después de algunaFuncion() ha sido invocada por TestFun(), pero se introduce antes de algunaFuncion(). También me gustaría obtener datos de reflexión sobre SomeFunction().


Encontré algo interesante en las respuestas de todos. La mejor respuesta a la pregunta es usar CastlePro DynamicProxy; sin embargo, esto no es lo que voy a usar para resolver mi problema porque requiere agregar una biblioteca a mi proyecto. Tengo solo unos pocos métodos que debo "rastrear", así que he optado por utilizar una metodología "básica" modificada, mezclada con la forma en que se implementa Dynamic Proxy. Explico esto en mi respuesta a mi propia pregunta a continuación.

Como nota, voy a buscar en el AOP y en la clase ContextBoundObject para algunas otras aplicaciones.

+0

Si encuentra que el ContextBoundObject algo útil por favor voten mi respuesta de -1 :) Es una buena solución si sólo desea utilizar bibliotecas del núcleo de .NET. –

Respuesta

5

Puede usar un proxy dinámico (Castle's DynamicProxy por ejemplo) para interceptar la llamada, ejecutar el código que desee y luego invocar su método o no, según sus necesidades.

+0

Respuesta correcta, enlace incorrecto. Este artículo al que vinculó se trata de la versión anterior 1.0, que es incompatible con v2.1, que es la versión actual. –

+0

Gracias Krzysztof - ¡He actualizado el enlace! –

2

utilizar un método * Core:

public int SomeFunction(string str) 
{ 
    Tracer(); 
    return SomeFunctionCore(str); 
} 

private int SomeFunctionCore(string str) 
{ 
    return 0; 
} 

Un número de las API .NET utilizar este (muchos lo hacen en WPF).

1

Quiere ver la Programación Orientada a Aspectos. Aquí hay una página que encontré para AOP en .NET: http://www.postsharp.org/aop.net/

La Programación Orientada a Aspectos implica separar las "cuestiones transversales" del código. Un ejemplo de esto es el registro: el registro existe (con suerte) en todo su código. ¿Deberían todos estos métodos realmente necesitan saber sobre el registro? Tal vez no. AOP es el estudio de separar estas preocupaciones del código con el que tratan e inyectarlas nuevamente, ya sea en tiempo de compilación o en tiempo de ejecución. El enlace que publiqué contiene enlaces a varias herramientas que se pueden usar tanto para el tiempo de ejecución en tiempo de compilación como para el tiempo de ejecución.

1

.NET tiene una clase llamada ContextBoundObject que puede usar para configurar interruptores de mensajes para hacer intercepción de llamadas siempre que no le importe derivar de una clase base esto le dará lo que está buscando sin tomar una dependencia de biblioteca .

+0

Pero es dolorosamente lento, hasta un punto en el que es completamente inutilizable. –

+0

No estoy de acuerdo con este comentario ... Lo he usado varias veces para desarrollar una solución y, aunque tiene una sobrecarga, está lejos de ser inutilizable. –

0

Si necesita hacer esto a gran escala (es decir, para cada función en un programa) y no desea alterar enormemente la fuente, puede buscar utilizando el .NET Profiling API. Es un poco complicado de usar, ya que tienes que crear objetos COM de subprocesos libres para hacerlo, pero te da una enorme cantidad de control sobre la ejecución del programa.

0

Esta es la solución que he elegido para resolver mi problema. Dado que no existe una forma automática (atributo similar) para hacer que esto funcione, creo que es lo menos molesto y permite que la funcionalidad se active y desactive al elegir qué clase se instanciará. Tenga en cuenta que esto no es la mejor respuesta a mi pregunta, pero es la mejor respuesta para mi situación particular.

Lo que sucede es que simplemente estamos derivando una segunda clase que a veces o siempre se creará una instancia en lugar de su padre. Los métodos que queremos rastrear (o rastrear) se declaran virtuales y se vuelven a implementar en la clase derivada para realizar las acciones que queremos rastrear y luego se llama a la función en la clase padre.

public class TestClass { 

    public virtual void int SomeFunction(string /*str*/) 
    { 
    return 0; 
    } 


    public void TestFun() 
    { 
    SomeFunction(""); 
    } 

} 


public class TestClassTracer : TestClass { 

    public override void int SomeFunction(string str) 
    { 
    // do something 
    return base.SomeFunction(str); 
    } 

} 
2

¡Utilice a los delegados!

delegate void SomeFunctionDelegate(string s); 

void Start() 
{ 
    TraceAndThenCallMethod(SomeFunction, "hoho"); 
} 

void SomeFunction(string str) 
{ 
    //Do stuff with str 
} 

void TraceAndThenCallMethod(SomeFunctionDelegate sfd, string parameter) 
{ 
    Trace(); 
    sfd(parameter); 
} 
Cuestiones relacionadas