tags:

views:

239

answers:

0

Hello,

I have encountered a problem I can't solve. I'm hoping someone can give me a nudge in the right direction. As one my first projects to learn AOP and PostSharp in particular, I decided to attempt to monitor SqlConnection lifespans in an application. My code looks like this:

using System; using System.Collections.Generic; using System.Text; using PostSharp.Laos; using PostSharp.Extensibility;

namespace Tests { [Serializable] [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Event | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple = true, Inherited = true)] public class LifespanMonitorAspect : PostSharp.Laos.OnMethodInvocationAspect { private DateTime _startTime; private Metric _metric;

    public override void OnInvocation(MethodInvocationEventArgs eventArgs)
    {
        System.Reflection.MethodInfo method = eventArgs.Delegate.Method;

        if (_isEnabled)
        {
            if (method.IsConstructor)
            {
                _startTime = DateTime.Now;
            }
            else if (method.Name == "Dispose")
            {
                if (_metric == null)
                {
                    ISession obj = eventArgs.Delegate.Target as ISession;

                    // Get the name used for the metric location
                    string name = eventArgs.Delegate.Target.GetType().FullName + "." + eventArgs.Delegate.Method.Name;

                    // Proprietary statistics system.
                    if (obj != null)
                    {
                        _metric = Metric.Lookup(name, obj.SessionKey);
                    }
                    else
                    {
                        _metric = Metric.Lookup(name, AnonymousObjectKey);
                    }

                }

                TimeSpan ts = DateTime.Now - _startTime;

                // Record in proprietary statistics system
                _metric.Add(new MetricValue(ts.Milliseconds));

            }
        }

        // Invoke the method 
        base.OnInvocation(eventArgs);
    }

}

I've eliminated some non-relevant code but the goal is to capture the time that a SqlConnection object is created and then calculate the lifespan in the Dispose() method. Using that, I can record in our proprietary statistics gathering system.

My test program looks like this:

using System; using System.Collections.Generic; using System.Text; using System.Data.SqlClient; using Tests;

[assembly: LifespanMonitorAspect(AttributeTargetAssemblies = "System.Data", AttributeTargetTypes = "System.Data.SqlClient.SqlConnection")]

namespace Tests { class Program { static void Main(string[] args) { string cs = "some connect string"; SqlConnection db = new SqlConnection(cs); db.Open(); SqlCommand cmd = db.CreateCommand(); db.Close(); db.Dispose(); } } }

The problem I am encountering is that the aspect code is not triggered on the constructor nor the Dispose method. In fact, the only method that is triggered is the CreateCommand call. I suspected this might have to do with the fact that SqlConnection is derived from a base class, so I tried this:

[assembly: LifespanMonitorAspect(AttributeTargetAssemblies = "System.Data.Common", AttributeTargetTypes = "System.Data.Common.DbConnection")]

but this did not yield any difference. I even tried this:

[assembly: LifespanMonitorAspect(AttributeTargetAssemblies = "System.Data.Common", AttributeTargetTypes = "System.Data.Common.IDbConnection")]

but no luck. Using some examples I found on codeproject ()http://69.10.233.10/KB/cs/ps-custom-attributes-2.aspx, I've successfully attached code to other libraries in the runtime, but I'm stuck on this one.

Any ideas? Thanks in advance!