The question came up today ‘How can I store my aspects in a single project in my solution and allow them to be usable across my application”
Luckily for us PostSharp follows DRY and SRP so this is fairly straight forward otherwise this would be silly. Updated my sample app ChlodnyWebApi to demonstrate this.
- First thing we will do is create a new Class Library project and name it Aspects
- Go ahead and delete the Class1.cs file
- Next we will create a new class with the name of ExceptionHandlerAttribute, this will be a very basic OnExceptionAspect. Copy the code below into it.
using Aspects; [assembly: ExceptionHandler(AttributePriority = 1)] [assembly: ExceptionHandlerAttribute(AttributePriority = 2, AttributeExclude = true, AttributeTargetTypes = "HpsErp.Common.AspectObject.*")] namespace Aspects { using System; using System.Diagnostics; using PostSharp.Aspects; [Serializable] public class ExceptionHandlerAttribute : OnExceptionAspect { (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public override void OnException(MethodExecutionArgs args) { if (args.Instance != null) { string messageOut = string.Format( "\n\n ----------{0} had an error ----------\n@ {1}:\n\n {2}\n\nStackTrace:{3}", args.Method.Name, DateTime.Now, args.Exception.Message, args.Exception.StackTrace); if (args.Exception.InnerException != null) { messageOut += string.Format("\n ---------- InnerException --------\n : {0}", args.Exception.InnerException); } Trace.WriteLine(messageOut); } args.FlowBehavior = FlowBehavior.Continue; } } }
- Now go to your main project (in our case ChlodnyWebApi)
- Add a reference to Aspects and PostSharp
- Open the class in the main project where you want to add the ExceptionHandlerAttribute. In our case we will open the CustomerController.cs and modify the GetCustomer method. Here is what the method looks like (you will also need to add a using Aspects to the top of the class.)
// Retrieve = GET [ExceptionHandlerAttribute] public IQueryable<Customer> GetCustomer() { bingMapsRest.GetLocationByAddress(); return this.contexts1.Customers.Where(c => c.Deleted == false); }
- Build your solution
- open your trusty IL decompiler in my case I use Telerik JustDecompile. Navigate to ChlodnyWebApi –> ChlodnyWebApi.Controllers –> CustomerController –> GetCustomer()
- the Method should look like this now (notice our exception handler has been applied)
public IQueryable<Customer> GetCustomer() { IQueryable<Customer> returnValue; try { this.bingMapsRest.GetLocationByAddress(); ParameterExpression parameterExpression = Expression.Parameter(typeof(Customer), "c"); ParameterExpression[] parameterExpressionArray = new ParameterExpression[1]; parameterExpressionArray[0] = parameterExpression; IQueryable<Customer> customers = this.contexts1.Customers.Where<Customer>(Expression.Lambda<Func<Customer, bool>>(Expression.Equal(Expression.Property(parameterExpression, (MethodInfo)MethodBase.GetMethodFromHandle(Deleted)), Expression.Constant((bool)0, typeof(bool))), parameterExpressionArray)); returnValue = customers; } catch (Exception exception1) { Exception exception = exception1; MethodExecutionArgs methodExecutionArg = new MethodExecutionArgs(this, null); MethodBase methodBase = CustomerController.CustomerController.m2; methodExecutionArg.Method = methodBase; methodExecutionArg.Exception = exception; CustomerController.CustomerController.a0.OnException(methodExecutionArg); switch (methodExecutionArg.FlowBehavior) { case FlowBehavior.Continue: { methodExecutionArg.Exception = null; break; } case FlowBehavior.Return: { methodExecutionArg.Exception = null; returnValue = (IQueryable<Customer>)methodExecutionArg.ReturnValue; break; } case FlowBehavior.ThrowException: { throw methodExecutionArg.Exception; } default: { throw; } } } return returnValue; }
- To see a live example go to the git hub or codeplex repo.