Click here to Skip to main content
15,884,849 members
Articles / Programming Languages / C#

Applied Use of LinFu/Cecil and Aspect-Oriented Programming Concepts - A Library

Rate me:
Please Sign up or sign in to vote.
4.88/5 (8 votes)
4 Sep 2008CPOL17 min read 35.1K   160   32  
A library of useful functionality using Aspect-Oriented Programming concepts, and implemented using the LinFu and Cecil.Mono projects/frameworks.
using System.Diagnostics;
using System;
using System.Reflection;
using System.Windows.Forms;

using System.Collections.Generic;
using System.IO;
using System.ComponentModel;
using System.Collections;
using System.Text;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;

using BrainTechLLC.ThreadSafeObjects;
using LinFu.AOP;
using LinFu.AOP.Interfaces;

namespace BrainTechLLC
{
	public class RestrictPropertyChangeWrapper : AroundMethodBase, IAroundInvoke
	{		
		public override void BeforeInvoke(IInvocationContext context)
		{
			Execute(context, CutpointType.Before);
		}

		public override void AfterInvoke(IInvocationContext context, object returnValue)
		{
			// If we skipped executing property set {...} this time, restore 
			// any previous IsInterceptionDisabled value that may have been set
			if (context.ExtraInfo != null)
				RestoreIsInterceptionDisabledFlag(context);
		}

		private void Execute(IInvocationContext context, CutpointType when)
		{
			object thisObject = context.Target;
			Type t = thisObject.GetType();

			// Method name comes in as set_PropertyName
			// Grab the property name by taking the substring starting at position 4
			string propInfoName = context.TargetMethod.Name.Substring(4);
			
			// Get property info and other details about the property being set
			PropInfo propInfo = t.GetPropInfo(propInfoName);

			// Read any RestrictPropertyChangeAttribute attributes attached to the property
			RestrictPropertyChangeAttribute[] attrs = propInfo.GetAttributes<RestrictPropertyChangeAttribute>();

			if (attrs != null && attrs.Length > 0)
			{
				// Read the old property value and record the new one
				object oldValue = propInfo.GetValue(thisObject);
				object newValue = context.Arguments[0];

				for (int n = 0; n < attrs.Length; n++)
				{
					RestrictPropertyChangeAttribute attr = attrs[n];

					// See if the property change is restricted
					Exception ex = attr.IsRestricted(thisObject, t, propInfo.Name, oldValue, newValue, context);

					if (ex != null)
					{
						// Send notification regarding the restriction, if possible
						ISupportsPropertyChangeRestrictedNotify notify = thisObject as ISupportsPropertyChangeRestrictedNotify;
						
						if (notify != null)
							notify.NotifyPropertyChangeRestricted(context, propInfo.PropertyInfo, oldValue, newValue, ex);

						// Mark that the original method should NOT be executed
						SetInterceptionDisabledFlag(context, true);

						if (attr.ThrowOnException)
							throw ex;
					}
				}
			}
		}

		private void RestoreIsInterceptionDisabledFlag(IInvocationContext context)
		{
			IModifiableType mod = context.Target as IModifiableType;

			// Set the flag back to its original (pre-method-call) value
			mod.IsInterceptionDisabled = Convert.ToBoolean(context.ExtraInfo);

			// Blank out ExtraInfo to mark that we're done using it
			context.ExtraInfo = null;
		}

		private void SetInterceptionDisabledFlag(IInvocationContext context, bool value)
		{
			IModifiableType mod = (context.Target as IModifiableType);

			// Store the old value of the IsInterceptionDisabled flag
			context.ExtraInfo = mod.IsInterceptionDisabled;

			// Mark that we do not want to execute the original method's code
			mod.IsInterceptionDisabled = true;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Troppus Software
United States United States
Currently working as a Senior Silverlight Developer with Troppus Software in Superior, CO. I enjoy statistics, programming, new technology, playing the cello, and reading codeproject articles. Smile | :)

Comments and Discussions