AspectExamples.zip
Introduction
This article is all about aspect orientated programming (AOP).
Here is some tech speak about AOP, from some sources who are more than likely
more ellequant than me
Aspect-oriented programming entails breaking down program logic into
distinct parts (so-called concerns, cohesive areas of functionality). All
programming paradigms support some level of grouping and encapsulation of
concerns into separate, independent entities by providing abstractions (e.g.
procedures, modules, classes, methods) that can be used for implementing,
abstracting and composing these concerns. But some concerns defy these forms of
implementation and are called crosscutting concerns because they "cut across"
multiple abstractions in a program.
Logging exemplifies a crosscutting
concern because a logging strategy necessarily affects every logged part of the
system. Logging thereby crosscuts all logged classes and methods.
All AOP implementations have some crosscutting expressions that
encapsulate each concern in one place. The difference between implementations
lies in the power, safety, and usability of the constructs provided. For
example, interceptors that specify the methods to intercept express a limited
form of crosscutting, without much support for type-safety or debugging.
http://en.wikipedia.org/wiki/Aspect-oriented_programming
Aspect-Oriented Software Development (AOSD), sometimes just called Aspect-Oriented Programming (AOP), is a new approach to software design that addresses modularity problems that are not handled well by other approaches, including Structured Programming and Object-Oriented Programming (OOP). AOSD complements, but doesn't replace those approaches.
Typical enterprise and internet applications today have to address "concerns" like security, transactional behavior, logging, etc.. The subsystems that provide these services can be implemented in a modular way. However, to use these services, you must insert the same "boilerplate" code fragments into various places in the rest of the application to invoke these services. This violates the "don't repeat yourself" (DRY) principle and it compromises the overall system modularity, because the same invocation code is scattered throughout the application.
For example, if you want to control access to certain services in your application, you could insert authorization-checking boilerplate at the beginning of every method that needs this control. Because this redundant boilerplate appears in many places in the code, it would now be difficult and error prone to modify or replace this security approach later, should that become necessary. Also, your application code is now tangled with code for the security (and probably other) concerns, which both compromises clarity and makes it hard to reuse your code in another context, since you would have to drag along the same security approach, which may not be appropriate.
Because concerns like security typically cut across a number of application module boundaries (e.g., classes). We call them cross-cutting concerns.
Note that the loss of modularity is at the intersection between the different concerns. AOP restores modularity by developing the cross-cutting concerns, or aspects, in isolation and then combining them with other modules using declarative or programmatic mechanisms that are modular. That is, the points of intersection are defined once, in one place, making them easy to understand and maintain. The other modules require no modifications to be advised by the aspects. This "intersection" process, sometimes called weaving, can occur at build or run time. AOSD weaving is a key innovation that provides very fine grained query and composition semantics. Where traditional code linking has the ability to resolve method and variable names, weaving adds the ability to replace method bodies with new implementations, insert code before and after method calls, instrument variable reads and writes, and even associate new state and behavior with existing classes, typically for adding "mixin" behaviors.
What is Aspect-Oriented Software Development?
The Different Type Of Aspect Frameworks Out There
There are a few different options available when doing aspect orientated
programming (henceforth known as AOP) in .NET. These options/frameworks broadly
fall into one of 2 categories:
Proxy Based AOP Frameworks
Some/a lot of you may have heard of Dependency Injection and even used
IOC/Dependency Injection containers such as Castle/Unity/StructureMap/Spring before.
Well it just
so happens that it is quite common for some of these IOC/Dependency Injection containers to use
proxies that wrap the real implementation (source object) that is being stored
within the IOC/Dependency Injection container. For example Castle uses a class called DynamicProxy
while Unity offers TransparentProxy
and VirtualMethodProxy
objects. So now that
we know that there are some proxies in use (at least in some of these IOC/Dependency Injection containers), it is not so hard to imagine that we can use a proxy to intercept
calls to the real object, where by any virtual
methods/properties (which are just methods really) can be interecpted by the
proxy before it calls the real object. Where the user is free to create
whatever type of interception code they wish to, which is usually
accomplished by implementing a particular interface or extending a certain
class etc etc
This diagram may help to illustrate how proxy based AOP works

The problems with using this type of AOP framework is that you are forced
into uing a DI/IOC paradigm which you may not want to use for any other reason
that to allow AOP. What that means to you the developer, is that any type you
wish to use AOP with must exist in the IOC/Dependency Injection container and must be resolved from
it. This forces a certain type of programming on you, which as I say you may not
want. The other problem with proxy based AOP frameworks is the fact that they
are using proxies usually means that any method/property you wish to allow to be
intercepted must be marked as Virtual
. Now you may or may not be
able to live with this, but it does open up certain dangers that some other bit
of code could mistakenly overrides these methods/properties due to them being
virtual, which could indicate an extension point to someone looking at the code
who is not familiar with the overall picture.
One final thing that proxy based AOP frameworks do not seem to be able to
cope with, it to introduce aspects arounf backing fields, or around statis
types, methods, and properties.
IL Weaving Based AOP Frameworks
IL Weaving is an interesting new thing that has only become fairly mainstream
(at least I think so anyway), over the past year or 2. So what is this IL
Weaving of which I speak?
Well we all know that this is what the normal workflow for .NET code looks
like right?

Well lets now consider the following diagram, which illustrates what happens
in IL Weaving based AOP frameworks.

Essentially what happens is that you existing code based in extended by
either implementing special interfaces or inherting from a particular base
class, where you can enter you new code. Then at compile time, the new code you
entered into these interfaces implementation/classes is obtained, and the IL for
the original code and these new bits of code is obtained and literally writen
out into the Assembly instead of the original IL code.
Pure IL Weaving is 100% possible using a not very well known
Dll called Mono.Cecil
which is part of the
Mono
project. Although IL weaving is quite advanced, it is something that I urge you all to have
an investigative look at, as at least one of the existing AOP frameworks
that I have chosen to look at uses Mono.Cecil
internally. I will talk
about how Mono.Cecil
works in some detail when I
discuss the AOP frameworks that rely on
Mono.Cecil
.
The main problem with this type of code is that the workflow of the original
code is not longer clear, but saying that, that is also the case with Proxy
based AOP frameworks. What IL weaving based frameworks have in their favour is
the fact that they are not using a Proxy, they will literally write out new IL,
so they do not require any intecption method/properties to be virtual at all.
This is the case as the IL weaving framework will just grab the orginals methods
IL and pre/post pend to it, or possibly replace it all with new IL. The other
neat thing with IL weaving based AOP frameworks (ok some are more advanced than
others) is that you can even introduce new members, fields, events etc etc and
there are no problems working with static types, they are just types after all,
and as such have IL too.
What Are We Going To Try And Achieve
Ok so now that you have a basic idea of what AOP is about and how some of the
existing frameworks out there may provide us .NET developers with the tools to
write our own aspects, lets briefly talk about what the attached demo app(s) do.
I have provided 4 different AOP framework demos, where possible I have tried
to make them all do the same thing, that has not been possible in all cases, but
generally it has been acheived.
So what has been achieved then?
Well as some of you may know I am quite into my WPF development, and as such
there is one interface above all others that I implement all the time. This
interface is the System.ComponentModel.INotifyPropertyChanged
interface (INPC from here on) which
looks like this:
namespace System.ComponentModel
{
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
}
Which is typically implemented like this:
public class MainWindowViewModel : INotifyPropertyChanged
{
private int someProperty;
public int SomeProperty
{
get { return someProperty; }
set
{
someProperty=value;
RaisePropertyChanged("SomeProperty");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Now this interface relies on a magic string being passed into the RaisePropertyChanged
method. And as we
all know strings are not refactorable. In fact the use of the INPC interface is so common, that many developers including
myself have come up with different ways of getting rid of this magic string. Solutions range from using T4 templates,
to using Expression Trees, to using StackFrame
s, believe me I have seen a few implementations.
The things is with all these approaches you still need to do some work. Which got me thinking wouldn't it be nice if we could
just attribute up an auto property to tell it it was an INPC attribute, something like this:
public class MainWindowViewModel : INotifyPropertyChanged
{
[INPCAttribute]
public virtual string DummyProp1 { get; set; }
[INPCAttribute]
public virtual string DummyProp2 { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Which got me thinking even more, well if I can fire the INPC PropertyChanged
event using some aspect orientated programming, perhaps
I could even write an aspect that would implement the System.ComponentModel.INotifyPropertyChanged
interface automatically for me
which would lead to code like this:
public class DummyModel
{
[AddINPCAttribute]
public virtual string DummyModelProp1 { get; set; }
[AddINPCAttribute]
public virtual string DummyModelProp2 { get; set; }
public virtual string DummyModelProp3 { get; set; }
}
Ok this would not suit every property and sometimes you would want to manually control when to fire the INPC event, or add more code in the setter
of the property, but for 80% auto firing INPC events may be more than suitable.
Largely I have been very successful and managed just that, and that is what the rest of the article is going to talk about.
However before we carry on, I just wanted to go back to something I mentioned
earlier, where I said that I tried to make all the different AOP framework do
the same thing, well I tried but in some cases I either lacked the motivation or
the skills. I have chosen to evaluate 4 AOP frameworks, and these along with
what I did with them is shown in the table below:
AOP Framework |
What I Managed To Achieve |
Castle |
- Created an property targetting attribute, that when applied to a
class that ALREADY implements
INotifyPropertyChanged will call
the INotifyPropertyChanged PropertyChanged
event when the property is set
- Created a property targetting attribute, that when applied to a
class that DOES NOT implement
INotifyPropertyChanged
will automatically implement the INotifyPropertyChanged
interface and will call the PropertyChanged event when
the property with the attribute is set
|
Unity |
- Created an property targetting attribute, that when applied to a
class that ALREADY implements
INotifyPropertyChanged will call the
INotifyPropertyChanged PropertyChanged event
when the property is set
- Globally applied a inteception behavior that will cause any
intercepted property setter, to fire the
INotifyPropertyChanged PropertyChanged event
when the property is set, if the target type ALREADY
implements INotifyPropertyChanged
|
PostSharp (not free) |
- Created a class targetting attribute, that when applied to a
class that DOES NOT implement
INotifyPropertyChanged
will automatically implement the INotifyPropertyChanged
interface and will call the PropertyChanged event when a
property is set
|
LinFu.AOP * |
- Created an property targetting attribute, that when applied to a
class that ALREADY implements
INotifyPropertyChanged will call the
INotifyPropertyChanged PropertyChanged event
when the property is set
|
* Has dependency on Mono.Cecil
Digging Deep Into The Demo Code Examples
The next subsection will outline how the various AOP frameworks that I chose
to look at do what I just discussed in the table above.
Castle (Proxy Based)
Castle is an IOC/Dependency Injection Container. Now recall what I said I managed to achieve using Castle
Objective 1
Created an property targetting attribute, that when applied to a
class that ALREADY implements INotifyPropertyChanged
will call
the INotifyPropertyChanged
PropertyChanged
event when the property is set
Objective 2
Created a property targetting attribute, that when applied to a
class that DOES NOT implement INotifyPropertyChanged
will automatically implement the INotifyPropertyChanged
interface and will call the PropertyChanged
event when
the property with the attribute is set
So now lets look at how we managed to achieve both of these objectives, starting with Objective 1.
Objective 1 STEP 1 : Create A INPCAttribute
The 1st step is straight forward, we simple create a standard .NET attribute as follows:
[AttributeUsage(AttributeTargets.Property)]
public class INPCAttribute : Attribute
{
}
Is can be seen that nothing much happens in this code, it is just a marker that we will use to mark properties that will need to call the INPC PropertyChanged
event when set.
Objective 1 STEP 2 : Creating A INPC IInterceptor
In Castle method inception (and remember properties are just methods get_xxxx/set_xxxx) is achieved using a special castle interface called IInterceptor
, which for objective 1 can be implemented as follows:
This interceptor is automatically applied to any Type in the ViewModels namespace, by the ViewModelInstaller
(we will see that soon). When this inteceptor is called it will then examine the method (and property changes are just get_xxx()/set_xxx() methods after all), and look for a INPCAttribute
, which is a standard Attribute which if found will cause the method invocation to also fire the INPC PropertyChanged
event on the target object.
public class NotifyPropertyChangedInterceptor : IInterceptor
{
#region IInterceptor Implementation
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
if (invocation.Method.Name.StartsWith("set_"))
{
string propertyName = invocation.Method.Name.Substring(4);
var pi = invocation.TargetType.GetProperty(propertyName);
if (!pi.HasAttribute<INPCAttribute>())
return;
FieldInfo info = invocation.TargetType.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic)
.Where(f => f.FieldType == typeof(PropertyChangedEventHandler))
.FirstOrDefault();
if (info != null)
{
PropertyChangedEventHandler evHandler =
info.GetValue(invocation.InvocationTarget) as PropertyChangedEventHandler;
if (evHandler != null)
evHandler.Invoke(invocation.TargetType,
new PropertyChangedEventArgs(propertyName));
}
}
}
#endregion
}
Objective 1 STEP 3 : Using The INPCAttribute On A Target Type
Now that we have a INPCAttribute
all we need to do is apply this INPCAttribute
to some target type. In the demo app this INPCAttribute
is applied to the MainWindowViewModel
type as follows:
public class MainWindowViewModel : INotifyPropertyChanged
{
#region Ctor
public MainWindowViewModel()
{
DummyModel = ContainerWiring.Instance.Container.Resolve<DummyModel>();
}
#endregion
#region Public Properties
[INPCAttribute]
public virtual string DummyProp1 { get; set; }
[INPCAttribute]
public virtual string DummyProp2 { get; set; }
public string DummyProp3 { get; set; }
public DummyModel DummyModel { get; set; }
#endregion
#region INPC Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Objective 1 STEP 4 : Configuring Castle For Inception For MainWindowViewModel
Now that we have a type that makes use of the INPCAttribute
we need to make sure Castle is configured to use it. This is done within the ContainerWiring
class as follows:
public class ContainerWiring
{
#region Data
private static readonly Lazy<ContainerWiring> instance
= new Lazy<ContainerWiring>(() => new ContainerWiring());
private IWindsorContainer container;
#endregion
#region Ctor
private ContainerWiring()
{
container = new WindsorContainer();
}
#endregion
#region Public Methods/Properties
public static ContainerWiring Instance
{
get
{
return instance.Value;
}
}
public IWindsorContainer Container
{
get { return container; }
}
public void SetUp()
{
container.Install(FromAssembly.This());
}
public void TearDown()
{
if (container != null)
{
container.Dispose();
}
container = null;
}
#endregion
}
NOTE : I am using a Lazy<T>
singleton approach here, which is my latest favourite way of doing singletons as its both Lazy and thread safe, and reads well as well and does not relay on any compiler related tricks.
Mmmm no mention of any inception code there, just some Setup()
method....Curious. What actually happens is that the Setup()
method is responsible for installing everything that the demo app requires. But what is that actually doing, well in Castle, you can inherit from another interface called IWindsorInstaller
which when implemented will do whatever you specified in you implementation, and will allow the IWindsorInstaller
implementing class to be installed into the Castle container.
The demo app features 3 installers, 2 of which I will talk about now, and 1 I will talk about later.
ViewModelInstaller
Will install inecption for any Type that in the same namespace as the MainWindowViewModel
, and that is how we apply intecption to the MainWindowViewModel
Type we just saw above.
public class ViewModelInstaller : IWindsorInstaller
{
#region IWindsorInstaller Implementation
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(AllTypes.FromThisAssembly()
.Where(Castle.MicroKernel.Registration.Component.
IsInSameNamespaceAs<MainWindowViewModel>())
.Configure(c => c.LifeStyle.Transient
.Interceptors(typeof(NotifyPropertyChangedInterceptor))));
}
#endregion
}
InterceptorInstaller
Any custom interceptors must also be installed into the Castle container in order to, well, um, actually intercept anything. So here is the InterceptorInstaller
from the demo app.
public class InterceptorInstaller : IWindsorInstaller
{
#region IWindsorInstaller Implementation
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(AllTypes.FromThisAssembly().BasedOn<IInterceptor>());
}
#endregion
}
Objective 1 STEP 5 : Use The MainWindowViewModel
So now we have all the pieces we just need to make use of this intercepted type. So in the demo app this is done within MainWindow
as follows:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainWindowViewModel viewModel = ContainerWiring.Instance.Container.Resolve<MainWindowViewModel>();
this.DataContext = viewModel;
(viewModel as INotifyPropertyChanged).PropertyChanged += MainWindowViewModel_PropertyChanged;
}
private void MainWindowViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MessageBox.Show(string.Format("{0} property changed in MainWindowViewModel", e.PropertyName));
}
}
You can see above that we get the inception enabled MainWindowViewModel
from the Castle container, and since the MainWindowViewModel
type makes use of the special INPCAttribute
, we should end up calling the INPC PropertyChanged
event whenever a property is set in the inception enabled MainWindowViewModel
Type.
And to prove that works here is a screen shot of that running:

So that was all we had to do to meet Objective 1, So lets now have a look at Objective 2, which just to remind ourselves looked like this:
Objective 2
Created a property targetting attribute, that when applied to a
class that DOES NOT implement INotifyPropertyChanged
will automatically implement the INotifyPropertyChanged
interface and will call the PropertyChanged
event when
the property with the attribute is set
Objective 2 STEP 1 : Create A AddINPCAttribute
As with Object 1, this 1st step is straight forward enough, we simple create a standard .NET attribute as follows:
[AttributeUsage(AttributeTargets.Property)]
public class AddINPCAttribute : Attribute
{
}
Is can be seen that nothing much happens in this code, it is just a marker that we will use to mark properties that will need to call the INPC PropertyChanged
event when set. But this time the target type, will be made to implement INotifyPropertyChanged
interface directly by the Castle Container.
Objective 2 STEP 2 : Creating A Add INPC IInterceptor
As befoe we inherit from the special castle interface called IInterceptor
, but this time the implementation is very different. As we actually want to add the implementation of the INotifyPropertyChanged
interface on the target object.
So what we have is this:
public class AddNotifyPropertyChangedInterceptor : IInterceptor
{
#region Data
private PropertyChangedEventHandler handler;
#endregion
#region IInterceptor Implementation
public void Intercept(IInvocation invocation)
{
string methodName = invocation.Method.Name;
object[] arguments = invocation.Arguments;
object proxy = invocation.Proxy;
bool isINPC = false;
try
{
if (invocation.TargetType != null)
{
PropertyInfo realProp = invocation.TargetType.
GetProperty(invocation.Method.Name.Substring(4));
isINPC = realProp.HasAttribute<AddINPCAttribute>();
}
}
catch { }
if (invocation.Method.DeclaringType.Equals(typeof(INotifyPropertyChanged)))
{
if (methodName == "add_PropertyChanged")
StoreHandler((Delegate)arguments[0]);
if (methodName == "remove_PropertyChanged")
RemoveHandler((Delegate)arguments[0]);
}
if (!ShouldProceedWithInvocation(methodName))
return;
invocation.Proceed();
if (isINPC)
NotifyPropertyChanged(methodName, proxy);
}
#endregion
#region Protected Methods
protected void OnPropertyChanged(Object sender, PropertyChangedEventArgs e)
{
var eventHandler = handler;
if (eventHandler != null) eventHandler(sender, e);
}
protected void RemoveHandler(Delegate @delegate)
{
handler = (PropertyChangedEventHandler)Delegate.Remove(handler, @delegate);
}
protected void StoreHandler(Delegate @delegate)
{
handler = (PropertyChangedEventHandler)Delegate.Combine(handler, @delegate);
}
protected void NotifyPropertyChanged(string methodName, object proxy)
{
if (methodName.StartsWith("set_"))
{
var propertyName = methodName.Substring(4);
var args = new PropertyChangedEventArgs(propertyName);
OnPropertyChanged(proxy, args);
}
}
protected bool ShouldProceedWithInvocation(string methodName)
{
var methodsWithoutTarget = new[] {
"add_PropertyChanged", "remove_PropertyChanged" };
return !methodsWithoutTarget.Contains(methodName);
}
#endregion
}
It can be seen that we handle Add/Remove of delegates for the INotifyPropertyChanged
interface implementation, and we also raise the INPC PropertyChanged
event, when a property is set that has our special AddINPCAttribute
.
Objective 2 STEP 3 : Using The AddINPCAttribute On A Target Type
Now that we have a AddINPCAttribute
all we need to do is apply this AddINPCAttribute
to some target type. In the demo app this AddINPCAttribute
is applied to the DummyModel
type as follows:
public class DummyModel
{
[AddINPCAttribute]
public virtual string DummyModelProp1 { get; set; }
[AddINPCAttribute]
public virtual string DummyModelProp2 { get; set; }
public virtual string DummyModelProp3 { get; set; }
}
Notice how this Type does NOT implement the INotifyPropertyChanged
interface at all.
Objective 2 STEP 4 : Configuring Castle For Inception For DummyModel
Now that we have a type that makes use of the AddINPCAttribute
we need to make sure Castle is configured to use it. This is done within the ContainerWiring
class that we saw previously
public class ContainerWiring
{
#region Data
private static readonly Lazy<ContainerWiring> instance
= new Lazy<ContainerWiring>(() => new ContainerWiring());
private IWindsorContainer container;
#endregion
#region Ctor
private ContainerWiring()
{
container = new WindsorContainer();
}
#endregion
#region Public Methods/Properties
public static ContainerWiring Instance
{
get
{
return instance.Value;
}
}
public IWindsorContainer Container
{
get { return container; }
}
public void SetUp()
{
container.Install(FromAssembly.This());
}
public void TearDown()
{
if (container != null)
{
container.Dispose();
}
container = null;
}
#endregion
}
And as I previously stated, most of the inception code is actually done via IWindsorInstaller
, and I already discussed 2 out of 3 of these from the demo app, we just need to discuss the last one, which adds the AddNotifyPropertyChangedInterceptor
to the DummyModel
type. This is done as follows:
ModelInstaller
Will install inecption for any Type that in the same namespace as the DummYModel
, and that is how we apply intecption to the DummyModel
Type we just saw above.
public class ModelInstaller : IWindsorInstaller
{
#region IWindsorInstaller Implementation
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(AllTypes.FromThisAssembly()
.Where(Castle.MicroKernel.Registration.Component.IsInSameNamespaceAs<DummyModel>())
.Configure(c => c.LifeStyle.Transient
.Proxy.AdditionalInterfaces(typeof(INotifyPropertyChanged))
.Interceptors(typeof(AddNotifyPropertyChangedInterceptor))));
}
#endregion
}
Objective 2 STEP 5 : Use The DummyModel
So now we have all the pieces we just need to make use of this intercepted type. So in the demo app this is done within MainWindowViewModel
which holds an instance of a DummyModel
:
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
DummyModel = ContainerWiring.Instance.Container.Resolve<DummyModel>();
}
.......
.......
.......
public DummyModel DummyModel { get; set; }
.......
.......
.......
}
Which we can listen to INPC PropertyChanged
event notification from, in the MainWindow
code behind as follows
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainWindowViewModel viewModel =
ContainerWiring.Instance.Container.Resolve<MainWindowViewModel>();
this.DataContext = viewModel;
(viewModel as INotifyPropertyChanged).PropertyChanged += MainWindowViewModel_PropertyChanged;
(viewModel.DummyModel as INotifyPropertyChanged).PropertyChanged += DummyModel_PropertyChanged;
}
private void MainWindowViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MessageBox.Show(string.Format("{0} property changed in MainWindowViewModel", e.PropertyName));
}
private void DummyModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MessageBox.Show(string.Format("{0} property changed in DummyModel", e.PropertyName));
}
}
And to prove that works here is a screen shot of that running:

Unity (Proxy Based)
Unity is an IOC/Dependency Injection Container that comes as a standalone application block, but I am using the one that comes with Enterprise Library 5.0.
Now recall what I said I managed to achieve using Unity
Objective 1
Created an property targetting attribute, that when applied to a
class that ALREADY implements INotifyPropertyChanged
will call the INotifyPropertyChanged
PropertyChanged
event
when the property is set
Objective 2
Globally applied a inteception behavior that will cause any
intercepted property setter, to fire the INotifyPropertyChanged
PropertyChanged
event
when the property is set, if the target type ALREADY implements INotifyPropertyChanged
So now lets look at how we managed to achieve both of these objectives, starting with Objective 1.
Objective 1 STEP 1 : Create A Special Inception Enabled Attribute
In Unity, inception can be enabled in a few different ways, but one common way is to inherit from a special Unity attribute, called the HandlerAttribute
. HandlerAttribute
is a attribute that when inherited from will allow you customs attribute to potentially inject aspects into the method call pipeline. The demo app uses this INPCAttribute
which inherits from HandlerAttribute
:
[AttributeUsage(AttributeTargets.Property)]
public class INPCAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new INPCHandler();
}
}
Is can be seen that nothing much happens in this code, instead this code creates another Type, called INPCHandler
. So that must be what we should look at next.
Objective 1 STEP 2 : Creating A Handler For The INPCAttribute
So as we just saw we have a special INPCAttribute
which creates a INPCHandler
. So what does a INPCHandler
look like?
public class INPCHandler : ICallHandler
{
#region ICallHandler Members
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn result = getNext()(input, getNext);
if (input.MethodBase.Name.StartsWith("set_"))
{
string propertyName = input.MethodBase.Name.Substring(4);
var pi = input.Target.GetType().GetProperty(propertyName);
if (pi.HasAttribute<INPCAttribute>())
{
FieldInfo info = input.Target.GetType().BaseType.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
.Where(f => f.FieldType == typeof(PropertyChangedEventHandler))
.FirstOrDefault();
if (info != null)
{
PropertyChangedEventHandler evHandler =
info.GetValue(input.Target) as PropertyChangedEventHandler;
if (evHandler != null)
evHandler.Invoke(input.Target.GetType(),
new PropertyChangedEventArgs(propertyName));
}
}
}
return result;
}
public int Order
{
get
{
return 0;
}
set
{
}
}
#endregion
}
It can be seen above that this INPCHandler
also inherits from a Unity interface called ICallHandler
. It is actually possible using Unity to apply handlers that implement ICallHandler
directly. But in this example the INPCHandler
was created by applying the INPCAttribute
to some target type. So what does implementing ICallHandler
give us. Well basically inheriting from ICallHandler
gives us the correct pipelilne hook to actual code out aspect. Any ICallHandler
implementation will be called at the appopriate time, providing we have configured Unity correctly.
It can also be seen from the above code that we are looking to see if we are in a property setter, and if we are we check to see if the Property we are setting, has the special INPCAttribute
on it, and if it does, we know we need to call the INPC PropertyChanged
event. So we just call it.
Objective 1 STEP 3 : Using The Special INPCAttribute On A Target Type
Now that we have a INPCAttribute
that we can apply that internally makes sure we get a INPCHandler
based ICallHandler
class, all we need to do is apply this INPCAttribute
to some target type. In the demo app this INPCAttribute
is applied to the MainWindowViewModel
type as follows:
public class MainWindowViewModel : INotifyPropertyChanged
{
#region Ctor
public MainWindowViewModel()
{
DummyModel = ContainerWiring.Instance.Container.Resolve<DummyModel>();
}
#endregion
#region Public Properties
[INPC]
public virtual string DummyProp1 { get; set; }
[INPC]
public virtual string DummyProp2 { get; set; }
public string DummyProp3 { get; set; }
public DummyModel DummyModel { get; set; }
#endregion
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyChanged(params string[] propertyNames)
{
foreach (string name in propertyNames)
{
OnPropertyChanged(new PropertyChangedEventArgs(name));
}
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, e);
}
}
#endregion
}
Objective 1 STEP 4 : Configuring Unity For Inception For MainWindowViewModel
Now that we have a type that makes use of the INPCAttribute
we need to make sure Unity is configured to use it. This is done within the ContainerWiring
class as follows:
public class ContainerWiring
{
#region Data
private static readonly Lazy<ContainerWiring> instance
= new Lazy<ContainerWiring>(() => new ContainerWiring());
private IUnityContainer container;
#endregion
#region Ctor
private ContainerWiring()
{
container = new UnityContainer();
}
#endregion
#region Public Methods/Properties
public static ContainerWiring Instance
{
get
{
return instance.Value;
}
}
public IUnityContainer Container
{
get { return container; }
}
public void SetUp()
{
container.AddNewExtension<Interception>();
container.RegisterType<MainWindowViewModel>();
container.RegisterType<DummyModel>();
PolicyDefinition policy = container.Configure<Interception>().
SetInterceptorFor<DummyModel>(new VirtualMethodInterceptor()).
SetInterceptorFor<MainWindowViewModel>(new VirtualMethodInterceptor()).AddPolicy("NotifyPolicy");
}
public void TearDown()
{
if (container != null)
{
container.Dispose();
}
container = null;
}
#endregion
}
Objective 1 STEP 5 : Use The MainWindowViewModel
So now we have all the peices we just need to make use of this intercepted type. So in the demo app this is done within MainWindow
as follows:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainWindowViewModel viewModel = ContainerWiring.Instance.Container.Resolve<MainWindowViewModel>();
this.DataContext = viewModel;
(viewModel as INotifyPropertyChanged).PropertyChanged += MainWindowViewModel_PropertyChanged;
}
private void MainWindowViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
string extraInfo = "Note as we are using an HandlerAttribute " +
"and a blanket PolicyDefinition \r\n " +
"of * we will get 2 * INPC events for MainWindowViewModel, " +
"But I am keeping this in to show you the options";
MessageBox.Show(string.Format("{0} property changed in MainWindowViewModel\r\n\r\n{1}",
e.PropertyName, extraInfo));
}
}
You can see above that we get the inception enabled MainWindowViewModel
from the UnityContainer, and since the MainWindowViewModel
type makes use of the special INPCAttribute
, we should end up calling the INPC PropertyChanged
event whenever a property is set in the inception enabled MainWindowViewModel
Type.
And to prove that works here is a screen shot of that running:

So that was all we had to do to meet Objective 1, So lets now have a look at Objective 2, which just to remind ourselves looked like this:
Objective 2
Globally applied a inteception behavior that will cause any
intercepted property setter, to fire the INotifyPropertyChanged
PropertyChanged
event
when the property is set, if the target type ALREADY implements INotifyPropertyChanged
Objective 2 STEP 1 : Creating A Global INPC Handler
So this time the objective is to create a global handler that can be applied to an entire class, and will automatically call the INPC PropertyChanged
event whenever a property is set. So for that we need to implement another Unity ICallHandler
which is shown below. Note this time there is no checking for any special attribute, as soon as we realize we are setting a property, and attempt is made to call the target types INPC PropertyChanged
event.
public class NonAttributedINPCHandler : ICallHandler
{
#region ICallHandler Members
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn result = getNext()(input, getNext);
if (input.MethodBase.Name.StartsWith("set_"))
{
string propertyName = input.MethodBase.Name.Substring(4);
var pi = input.Target.GetType().GetProperty(propertyName);
FieldInfo info = input.Target.GetType().BaseType.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
.Where(f => f.FieldType == typeof(PropertyChangedEventHandler))
.FirstOrDefault();
if (info != null)
{
PropertyChangedEventHandler evHandler = #
info.GetValue(input.Target) as PropertyChangedEventHandler;
if (evHandler != null)
evHandler.Invoke(input.Target.GetType(),
new PropertyChangedEventArgs(propertyName));
}
}
return result;
}
public int Order
{
get
{
return 0;
}
set
{
}
}
#endregion
}
It can be seen above that this NonAttributedINPCHandler
also inherits from a Unity interface called ICallHandler
. And for this implementation we intend to apply this globally to a certain target type, by providing Unity with the configuration information to apply it automatically to any property change.
Objective 2 STEP 2 : We Need A Target Type To Use This Global ICallHandler on
So we have a global ICallHandler
that we can apply in Unity when ever a property is set, but we still need a target type to apply it on to. So what does that target type look like, well for the demo code it looks like this:
public class DummyModel : INotifyPropertyChanged
{
public virtual string DummyModelProp1 { get; set; }
public virtual string DummyModelProp2 { get; set; }
public string DummyModelProp3 { get; set; }
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyChanged(params string[] propertyNames)
{
foreach (string name in propertyNames)
{
OnPropertyChanged(new PropertyChangedEventArgs(name));
}
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, e);
}
}
#endregion
}
Objective 2 STEP 3 : Configuring Unity For Inception For DummyModel
Now that we have a type that we want to apply the NonAttributedINPCHandler
to we need to make sure Unity is configured to use it. This is done within the ContainerWiring
class as follows:
public class ContainerWiring
{
#region Data
private static readonly Lazy<ContainerWiring> instance
= new Lazy<ContainerWiring>(() => new ContainerWiring());
private IUnityContainer container;
#endregion
#region Ctor
private ContainerWiring()
{
container = new UnityContainer();
}
#endregion
#region Public Methods/Properties
public static ContainerWiring Instance
{
get
{
return instance.Value;
}
}
public IUnityContainer Container
{
get { return container; }
}
public void SetUp()
{
container.AddNewExtension<Interception>();
container.RegisterType<MainWindowViewModel>();
container.RegisterType<DummyModel>();
PolicyDefinition policy = container.Configure<Interception>().
SetInterceptorFor<DummyModel>(new VirtualMethodInterceptor()).
SetInterceptorFor<MainWindowViewModel>(new VirtualMethodInterceptor()).AddPolicy("NotifyPolicy");
policy.AddMatchingRule(new PropertyMatchingRule("*", PropertyMatchingOption.Set));
policy.AddCallHandler<NonAttributedINPCHandler>();
}
public void TearDown()
{
if (container != null)
{
container.Dispose();
}
container = null;
}
#endregion
}
Note that is the entire listing for the ContainerWiring
class, so it also includes the previous Unity setup we saw for MainWindowViewModel
for objective 1. See how this time we use a instance of the Unity PolicyDefinition
, and we specify that any property setter should be matched and we add a call handler of our NonAttributedINPCHandler
handler, which calls the INPC PropertyChanged
event on the target object within the caller.
Now one interesting thing of note here is that, because the MainWindowViewModel
also has properties that can be set, it is also included in this blanket setter policy, but it also makes use of the INPCAttribute
on 2 of its properties ,which we talked about above. Which means when either of these 2 MainWindowViewModel
peoprties that also has the INPCAttribute
applied, we will get 2 INPC PropertyChanged
event notifications. One for the INPCAttribute
, and one from the globally applied NonAttributedINPCHandler
.
For the DummyModel
type, this is not the case, as it only uses the blanket setter policy, so only that rule applies.
Objective 2 STEP 4 : Use The DummyModel
Ok so now we have this DummyModel
type that will have a global Unity ICallHandler
applied to it, we just need to use one of these DummyModel
classes somewhere. For the demo app the MainWindowViewModel
(itself set for inception), uses a DummyModel
as a property as follows:
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
DummyModel = ContainerWiring.Instance.Container.Resolve<DummyModel>();
}
......
......
......
public DummyModel DummyModel { get; set; }
......
......
......
......
......
}
So we can also listen to INPC PropertyChanged
events from a MainWindowViewModel
s DummyModel
instance as follows, in the MainWindow
code behind.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainWindowViewModel viewModel =
ContainerWiring.Instance.Container.Resolve<MainWindowViewModel>();
this.DataContext = viewModel;
(viewModel.DummyModel as INotifyPropertyChanged).PropertyChanged += DummyModel_PropertyChanged;
}
private void DummyModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MessageBox.Show(string.Format("{0} property changed in DummyModel", e.PropertyName));
}
}
And here is a screen shot to show that working:

PostSharp (IL Weaving)
Now Postsharp is a premier legue AOP framework, arguably the most mature one
on the market, and it is very very feature rich, some of you may recall that it
also used to be free. Unfortunately all good things come to an end, and now one has to pay
for PostSharp, not that much though.
Anyway if you recall what I said I managed to achieve with PostSharp:
Created a class targetting attribute, that when applied to a
class that DOES NOT implement
INotifyPropertyChanged
will automatically implement the INotifyPropertyChanged
interface and will call the PropertyChanged
event when a
property is set
All that I need to do to achieve this is carry out a few steps.
STEP 1 : Reference PostSharp
Add a reference to the PostSharp.dll

STEP 2 : Create An Object We Want To Make INPC
For the attached demo app this looks like this where I am using a special
INPC aspect class which is discussed in Step3. Notice below that I am not
implementing INPC at all, nor do any of the properties have any attributes on
them, and also note that the properties are standard auto properties, and that
they are not virtual.
[INPC]
public class MainWindowViewModel
{
#region Public Properties
public string DummyProp1 { get; set; }
public string DummyProp2 { get; set; }
public string DummyProp3 { get; set; }
#endregion
}
STEP 3 : Implement The INPC Aspect
This is where the real work comes, we now have to implement the actual INPC
aspect class. Which looks like this:
[Serializable]
[IntroduceInterface(typeof(INotifyPropertyChanged),
OverrideAction = InterfaceOverrideAction.Ignore)]
[MulticastAttributeUsage(MulticastTargets.Class,
Inheritance = MulticastInheritance.Strict)]
public sealed class INPCAttribute : InstanceLevelAspect, INotifyPropertyChanged
{
#region Public Properties / Methods
[ImportMember("OnPropertyChanged", IsRequired = false,
Order = ImportMemberOrder.AfterIntroductions)]
public Action<string> OnPropertyChangedMethod;
[IntroduceMember(Visibility = Visibility.Family,
IsVirtual = true, OverrideAction = MemberOverrideAction.Ignore)]
public void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this.Instance, new PropertyChangedEventArgs(propertyName));
}
}
[IntroduceMember(OverrideAction = MemberOverrideAction.Ignore)]
public event PropertyChangedEventHandler PropertyChanged;
[OnLocationSetValueAdvice, MulticastPointcut(Targets = MulticastTargets.Property,
Attributes = MulticastAttributes.Instance | MulticastAttributes.NonAbstract)]
public void OnPropertySet(LocationInterceptionArgs args)
{
if (args.Value == args.GetCurrentValue()) return;
args.ProceedSetValue();
this.OnPropertyChangedMethod.Invoke(args.Location.Name);
}
#endregion
Now there is a lot going on there, but none of it is beyond us, so lets break it down a bit.
It can be seen below that this aspect not only calls NotifyPropertyChanged
whenever a property
is set, but is also introduces an actual implementation of the INotifyPropertyChanged
interface, and also introduces all the events and methods that are required by a
INotifyPropertyChanged
implementation. This is mainly achieved using the
IntroduceMemberAttribute.
And that is pretty much all there is to it. If we run the demo where we have the MainWindow
sets its DataContext
to a MainWindowViewModel
, we can indeed see that the
MainWindowViewModel
is indeed implementing INPC correctly.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainWindowViewModel viewModel = new MainWindowViewModel();
this.DataContext = viewModel;
(viewModel as INotifyPropertyChanged).PropertyChanged += MainWindowViewModel_PropertyChanged;
}
private void MainWindowViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
string extraInfo =
"Note as we are using an PostSharp, we simply not " +
"even have to have virtual properties in our MainWindowViewModel";
MessageBox.Show(string.Format(
"{0} property changed in MainWindowViewModel\r\n\r\n{1}", e.PropertyName, extraInfo));
}
}

LinFu.AOP (IL Weaving)
As LinFu.AOP internally relies on the Mono.Cecil
dll that I
mentioned right back at the start of the article, I thought I would just go
through a quick example of how Mono.Cecil
works.
How Mono Cecil Works
Now suppose I have a type that already implements INPC, and that we have a
standard INPC property such as FirstName shown below

And we also have an auto property LastName shown below, which as we can see
has some compiler generated bits to it.

And we examine the IL for the StartName full INPC property

Compared to the IL for the auto generated LastName property

We can see that they are nearly the same, but we are just missing a few IL
instructions

So if we could somehow manage to get in there are introduce these IL
instructions, and save the Assembly both the full INPC property and the auto
property should work the same. That is exactly what Mono.Cecil
allows us to do, and here is some example code to do just that.
CilWorker MSILWorker = prop.SetMethod.Body.CilWorker;
Instruction ldarg0 = MSILWorker.Create(OpCodes.Ldarg_0);
Instruction propertyName = MSILWorker.Create(OpCodes.Ldstr, prop.Name);
Instruction callRaisePropertyChanged = MSILWorker.Create(OpCodes.Call, raisePropertyChanged);
MSILWorker.InsertBefore(prop.SetMethod.Body.Instructions[0], MSILWorker.Create(OpCodes.Nop));
MSILWorker.InsertBefore(prop.SetMethod.Body.Instructions[prop.SetMethod.Body.Instructions.Count - 1],ldarg0);
MSILWorker.InsertAfter(ldarg0, propertyName);
MSILWorker.InsertAfter(propertyName, callRaisePropertyChanged);
MSILWorker.InsertAfter(callRaisePropertyChanged, MSILWorker.Create(OpCodes.Nop));
Obviously LinFu.AOP does a lot more than this, but it does use Cecil to do it. Which
generally works as shown above. I will obviously outline exactly how LinFu does
works in much finer detail, but I just felt that this little diversion was worth
while.
Ok so now back to LinFu
How LinFu Works
Anyway if you recall what I said I managed to achieve with LinFu:
Created an property targetting attribute, that when applied to a
class that ALREADY implements
INotifyPropertyChanged
will call the
INotifyPropertyChanged
PropertyChanged
event
when the property is set
All that I need to do to achieve this is carry out a few steps.
STEP 1 : Create The Aspect Intecepted Project
Unfortunately I could not seem to get LinFu to work unless I split the
project where aspects were to be woven and the aspects themselves into 2
projects. So I created a project which stored types that would be incepted, and
made sure I referenced the correct LinFu Dlls.

STEP 2 : Edit The MSBuild File For The Aspect Intecepted Project
The next thing I had to do was unload the project with the types that would
have the aspects woven into them. For the demo app this means the
LinFu.ViewModels project.
Then I had to add the following lines to the MSBUILD file for the project.
<PropertyGroup>
<PostWeaveTaskLocation>C:\Users\WIN7LAP001\Desktop\Downloads\LinFu_Src\LinFu.Aop.Tasks.dll</PostWeaveTaskLocation>
</PropertyGroup>
<UsingTask TaskName="PostWeaveTask" AssemblyFile="$(PostWeaveTaskLocation)" />
<Target Name="AfterBuild" Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<PostWeaveTask TargetFile="$(MSBuildProjectDirectory)\$(OutputPath)$(MSBuildProjectName).dll" InjectConstructors="true" />
</Target>
This step is VITAL, as it points to the PostWeaver Task that LinFu uses to inject the aspects.
After you have added this and made it point to the correct location on your
installation, you can reload the project.
STEP 3 : Marking Up A Class That You Want To Be INPC
This is the easy part we simply nee to come up with a simple Attribute that we can use as a marker that is applied to properties, that we can later examine to see if our aspect should fire the PropertyChanged
event of the incecepted type.
This attribute simple looks like this:
[AttributeUsage(AttributeTargets.Property)]
public class INPCAttribute : Attribute
{
}
STEP 3 : Using The INPCAttribute On A Target Type
The next step is to actually use this INPCAttribute
on a target type. For the LinFu demo this will be a MainWindowViewModel type that simply looks like this:
public class MainWindowViewModel : INotifyPropertyChanged
{
#region Public Properties
[INPCAttribute]
public string DummyProp1 { get; set; }
[INPCAttribute]
public string DummyProp2 { get; set; }
public string DummyProp3 { get; set; }
#endregion
#region INPC Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
You will notice that for this class we do actual implement the INotifyPropertyChanged
interface, so we are only expecting the LinFu aspect to call the INotifyPropertyChanged
interfaces, PropertyChanged
event that is already available within the MainWindowViewModel
.
That is all there is to this 1st LinFu AOP demo project, but next we need to look at the actual project that contains the aspect. So let's carry on and look at that shall we.
STEP 4 : Create The Aspect Weaving Project
As I mentioned in Step1, I could not seem to get LinFu to work unless I split the
project where aspects were to be woven and the aspects themselves into 2
projects. So I created a project which stored types that would be incepted. So we have already created the 1st of these project which is the project which stored types that would be incepted, so now we need to create the project that does the actual aspects and will produce the IL Woven code.
So lets have a look at this other project. It is a WPF application, that needs the following references

Where the LinFu.ViewModels
reference is the project we created in Step1.
STEP 5 : Create The Inception Code That Will Produce The Modified IL
LinFu uses interfaces for aspects, and has the special interface IInvokeAround
which you can implement to have your aspect run when you call a method/property (properties really are methods like get_XXXX/set_XXXX). So what we want is an aspect that will call the INotifyPropertyChanged
on a target type which implements the INotifyPropertyChanged
PropertyChanged
event
when a property is set
So here is the full code for the LinFu.AOP IInvokeAround
implementing inception code (it is quite simliar to the Castle/Unity code)
public class INPCMethodInvocation : IAroundInvoke
{
#region IAroundInvoke Members
public void AfterInvoke(IInvocationContext context, object returnValue)
{
if (context.TargetMethod.Name.StartsWith("set_"))
{
string propertyName = context.TargetMethod.Name.Substring(4);
var pi = context.Target.GetType().GetProperty(propertyName);
if (!pi.HasAttribute<INPCAttribute>())
return;
FieldInfo info = context.Target.GetType().GetFields(
BindingFlags.Instance | BindingFlags.NonPublic)
.Where(f => f.FieldType == typeof(PropertyChangedEventHandler))
.FirstOrDefault();
if (info != null)
{
PropertyChangedEventHandler evHandler =
info.GetValue(context.Target) as PropertyChangedEventHandler;
if (evHandler != null)
evHandler.Invoke(context.Target.GetType(),
new PropertyChangedEventArgs(propertyName));
}
}
}
public void BeforeInvoke(IInvocationContext context)
{
}
#endregion
}
What then happens in LinFu is that when compilation occurs the LinFu TaskWeaver
MSBUILD task will be run, which will examine any types that has Inception allowed and will then use the existing types method IL, and will then grab the IAroundInvoke implementations XXXXInvoke code and get the IL for that, and it will then form a new Instruction list of IL internally to LinFu, and it will then use the Mono.Cecil
.dlls IL ReWriting capabilities to rewrite the Assembly
to contain the original methods IL plus the IAroundInvoke
implementations XXXXInvoke IL. So in the case of IAroundInvoke implementations AfterInvoke
(...) we would end up with the original methods IL plus the IAroundInvoke implementations AfterInvoke IL being emmited to the modified Assembly IL.
Remember all of this is happening at compile time, it is not a runtime thing, the Assembly
is actually modified to have new IL woven into it. This is what Mono.Cecil
allows. And that is what LinFu uses internally.
STEP 6 : Applying The Aspect To A Target Type
So all good so far we have a aspect which we can apply to a type, we now just need to apply it. Here is how we do that we LinFu.AOP (Note I am using the same Lazy<T>
type singleton that I showed earlier). So lets see how we wire up inception in LinFu. This is done in the demo app in a single class called Inception, nothing special about that name, its just one I picked, and here is the full code for that class:
public class Inception
{
#region Data
private static readonly Lazy<Inception> instance
= new Lazy<Inception>(() => new Inception());
#endregion
#region Ctor
private Inception()
{
}
#endregion
#region Public Methods/Properties
public static Inception Instance
{
get
{
return instance.Value;
}
}
public void SetUp()
{
var mainWindowViewModelProvider =
new SimpleAroundInvokeProvider(new INPCMethodInvocation(),
c => c.TargetMethod.DeclaringType == typeof(MainWindowViewModel));
AroundInvokeRegistry.Providers.Add(mainWindowViewModelProvider);
}
#endregion
}
All we do is set up a new INPCMethodInvocation
interceptor which we created in step 5, and apply that to the MainWindowViewModel
type.Quite simple really...No?
STEP 7 : Using The Aspected Type
Now that we have all the pieces of the puzzle, all we need to is get ourselves one of these incercepted MainWindowViewModel
types, and make sure it works.
So here is how we do that:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var viewModel = new MainWindowViewModel();
this.DataContext = viewModel;
(viewModel as INotifyPropertyChanged).PropertyChanged += MainWindowViewModel_PropertyChanged;
viewModel.EnableInterception();
}
private void MainWindowViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MessageBox.Show(string.Format("{0} property changed in MainWindowViewModel", e.PropertyName));
}
}
And to prove it all works, here is a screen shot

Other Aspects
In this article I have really just concentrated on performing 1 or 2 INPC based aspects, but I hope you can all see how
you could roll your own aspects, such as a logging aspect where method calls are logged to file, or a thread aspect where a call
to the method would be marshalled to the UI thread, or even to throw a Exception
if the current users IWindowsPrincipal
object does not allow them access to
certain method etc etc.
That's It
This article took quite a bit of time to research and a bit of trial and error, so if you liked this article
and think it could be useful for you, or has maybe just given you some idea of
how aspects could work for you, could you maybe leave a comment/vote.
Many thanks folks.....Sacha