views:

554

answers:

5

Is there a way for me to add logging so that entering and exiting methods gets logged along with parameters automatically somehow for tracing purposes? How would I do so?

I am using Log4Net.

A: 

The best way to achieve this sort of thing is by using interception, There are a couple of ways to do this, though they all tend to be somewhat invasive. One would be to derive all your objects from ContextBoundObject. Here is an example of using this sort of approach. The other approach would be to use one of the existing AOP libraries to achieve this. Something like DynamicProxy from the Castle Project is at the core of many of these. Here are a few links: Spring.Net PostSharp Cecil

There are probably several others, and I know Castle Windsor, and Ninject both provide AOP capabilities on top of the IoC functionality.

Once AOP is in place you would simply write an interceptor class that would write the information about the method calls out to log4net.

I actually wouldn't be surprised if one of the AOP frameworks would give you that sort of functionality out of the box.

ckramer
+1  A: 

You could use a post-compiler like Postsharp. The sample from the website talks about setting up a tracer for entering/exiting a method, which is very similar to what you want.

Cameron MacFarland
+4  A: 

Have a look at:

http://stackoverflow.com/questions/25803/how-do-i-intercept-a-method-call-in-c#25825 http://stackoverflow.com/questions/91635/postsharp-il-weaving-thoughts

Also search SO for 'AOP' or 'Aspect Oriented Programming' and PostSharp...you get some interesting results.

Kev
+2  A: 

I'm not sure what your actual needs are, but here's a low-rent option. It's not exactly "automatic", but you could use StackTrace to peel off the information you're looking for in a manner that wouldn't demand passing arguments - similar to ckramer's suggestion regarding interception:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;

namespace TracingSample
{
    class Program
    {
        static void Main(string[] args)
        {
            DoSomething();
        }

        static void DoSomething()
        {
            LogEnter();

            Console.WriteLine("Executing DoSomething");

            LogExit();
        }

        static void LogEnter()
        {
            StackTrace trace = new StackTrace();
            if (trace.FrameCount > 1)
            {
                string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace;
                string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name;
                Console.WriteLine("Entering {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name);
            }
        }

        static void LogExit()
        {
            StackTrace trace = new StackTrace();
            if (trace.FrameCount > 1)
            {
                string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace;
                string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name;
                Console.WriteLine("Exiting {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name);
            }
        }
    }
}

You could combine something like the above example with inheritance, using a non-virtual public member in the base type to signify the action method, then calling a virtual member to actually do the work:

public abstract class BaseType
{
    public void SomeFunction()
    {

        LogEnter();
        DoSomeFunction();
        LogExit();
    }

    public abstract void DoSomeFunction();
}

public class SubType : BaseType
{
    public override void DoSomeFunction()
    {
        // Implementation of SomeFunction logic here...
    }
}

Again - there's not much "automatic" about this, but it would work on a limited basis if you didn't require instrumentation on every single method invocation.

Hope this helps.

Jared
A: 

The Decorator Pattern may help.

Vivek Kodira