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!