tags:

views:

376

answers:

8

What I am looking for is a way to call a method after another method has been invoked but before it is entered. Example:

public class Test {

  public void Tracer ( ... )
  {
  }

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

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

}

In the example above I would like to have Tracer() called after SomeFunction() has been invoked by TestFun() but before SomeFunction() is entered. I'd also like to get reflection data on SomeFunction().


I found something interesting in everyone's answers. The best answer to the question is to use Castle's DynamicProxy; however, this is not that I'm going to use to solve my problem because it requires adding a library to my project. I have only a few methods that I need to "trace" so I've chosen to go with a modified "core" methodology mixed with the way Dynamic Proxy is implemented. I explain this in my answer to my own question below.

Just as a note I'm going to be looking into AOP and the ContextBoundObject class for some other applications.

+1  A: 

Use a *Core method:

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

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

A number of the .NET APIs use this (lots do in WPF).

Bob King
+5  A: 

You can use a dynamic proxy (Castle's DynamicProxy for example) to intercept the call, run whatever code you wish, and then either invoke your method or not, depending on your needs.

Ben Hoffstein
Right answer, wrong link. This article you linked to is about old version 1.0 which is incompatible with v2.1 which is the current one.
Krzysztof Koźmic
Thanks Krzysztof - I updated the link!
Ben Hoffstein
+1  A: 

You want to look into Aspect Oriented Programming. Here's a page I found for AOP in .NET: http://www.postsharp.org/aop.net/

Aspect Oriented Programming involves separating out "crosscutting concerns" from code. One example of this is logging - logging exists (hopefully) across all of your code. Should these methods all really need to know about logging? Maybe not. AOP is the study of separating these concerns from the code they deal with, and injecting them back in, either at compile-time or run-time. The link I posted contains links to several tools that can be used for both compile-time and run-time AOP.

Chris Marasti-Georg
A: 

You would have to use some form of AOP framework like SpringFramework.NET to do that.

jop
+1  A: 

.NET has a class called ContextBoundObject that you can use to setup message sinks to do call interception as long as you don't mind deriving from a base class this will give you what you are looking for without taking an library dependency.

Brian ONeil
But it's painfully slow, up to a point where it's plain unusable.
Krzysztof Koźmic
I disagree with this comment... I have used it several times in developing solution and while it does have overhead, it is FAR from unusable.
Brian ONeil
A: 

If you need to do this on large scale (i.e. for every function in a program) and you don't want to hugely alter the source, you might look into using the .NET Profiling API. Its a little hairy to use since you have to build free-threaded COM objects to do so, but it gives you an enormous amount of control over the execution of the program.

Tim Farley
A: 

This is the solution I've choosen to solve my problem. Since there is no automatic (attribute like) way to make this work I feel it is the least obtrusive and allows the functionality to be turned on and off by choosing what class get instantiated. Please note that this is not the best answer to my question but it is the better answer for my particular situation.

What's going on is that we're simply deriving a second class that sometimes or always be instantiated in place of its parent. The methods that we want to trace (or otherwise track) are declared virtual and reimplemented in the derived class to perform whatever actions we want to trace and then the function is called in the parent class.

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

}
jr
A: 

Use delegates!

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