A few months ago, I had to implement a 'locking system' at work.
I will not elaborate to much on this system, but it's intention is that users can prevent that certain properties of certain entities are updated automatically;
The software-system in where I had to implement this functionality, keeps a large database up-to-date by processing and importing lots of data-files that we receive from external sources.
Because of that, in certain circumstances, users want to avoid that data that they've manually changed or corrected, gets overwritten with wrong information next time a file is processed.
The application where I'm talking about, makes heavy use of DataSets and I've been able to create a rather elegant solution for it.
At the same time, I've also been thinking on how I could solve this same problem in a system that is built around POCO's instead of Datasets, and that's what this post will be all about. :)
When the idea of implementing such a system first crossed my mind, I already realized that Aspects Oriented Programming could be very helpfull to solve this problem.
A while ago, I already played with Aspect Oriented Programming using Spring.NET.
AOP was very nice and interesing, but I found the runtime-weaving a big drawback. Making use of runtime weaving meant that you could not directly create an instance using it's constructor.
So, instead of:
MyClass c = new MyClass();you had to instantiate instances via a proxyfactory:
ProxyFactory f = new ProxyFactory (new TestClass());
f.AddAdvice (new MethodInvocationLoggingAdvice());
ITest t = (ITest)f.GetProxy();
I am sure that you agree that this is quite a hassle, just to create a simple instance. (Yes, I know, offcourse you can make abstraction of this by making use of a Factory...).
Recently however, I bumped at an article on Patrick De Boeck's weblog, where he was talking about PostSharp.
PostSharp is an aspect weaver for .NET which weaves at compile-time!
This means that the drawback that I just described when you make use of runtime-weaving has disappeared.
So, I no longer had excuses to start implementing a similar locking system for POCO's.
Bring it on
I like the idea of Test-Driven-Development, so I started out with writing a first simple test:
The advantage of writing your test first, is that you start thinking on how the interface of our class should look like.
This first test tells us that our class should have a
Lock and an
The purpose of the
Lock method is to put a 'lock' on a certain property, so that we can avoid that this property is modified at run-time.
IsLocked method is there to inform us whether a property is locked or not.
To define this contract, I've created an interface
ILockable which contains these 2 methods.
In order to get this first test working, I've created an abstract class
LockableEntity which inherits from one of my base entity-classes implements this interface.
LockableEntity class looks like this:
This is not sufficient to get a green bar on my first test, since I still need an
These pieces of code are sufficient to make my first test pass, so I continued with writing a second test:
As you can see, in this test-case I define that it should be possible to unlock a property. Unlocking a property means that the value of that property can be modified by the user at runtime.
To implement this simple functionality, it was sufficient to just add an
UnLock method to the
Simple, but now, a more challenging feature is coming up.
Now, we can already 'lock' and 'unlock' properties, but there is nothing that really prevents us from changing a locked property.
It's about time to tackle this problem and therefore, I've written the following test:
Running this test obviously gives a red bar, since we haven't implemented any logic yet.
The most simple way to implement this functionality, would be to check in the setter of the
Name property whether there exists a lock on this property or not.
If a lock exists, we should not change the value of the property, otherwise we allow the change.
I think that this is a fine opportunity to use aspects.
Creating the Lockable Aspect
As I've mentionned earlier, I have used PostSharp to create the aspects. Once you've downloaded and installed PostSharp, you can create an aspect rather easy.
There is plenty of documentation to be found on the PostSharp site, so I'm not going to elaborate here on the 'getting started' aspect (no pun intended).
Instead, I'll directly dive into the
Lockable aspect that I've created.
This is how the definition of the class that defines the aspect looks like:
Perhaps I should first elaborate a bit on how I would like to use this
I'd like to be able to decorate the properties of a class that should be 'lockable' with an attribute. Like this:
Decorating a property with the
Lockable attribute, means that the user should be able to 'lock' this property. That is, prevent that it gets changed after it has been locked.
To be able to implement this, I've created a class which inherits from the OnMethodInvocationAspect class (which eventually inherits from
Why did I choose this class to inherit from?
Well, because there exists no
OnPropertyInvocation class or whatsoever.
As you probably know, the getters and setters of a property are actually implemented as
set_ methods, so it is perfectly possible to use the
OnMethodInvocationAspect class to add extra 'concerns' to the property.
This extra functionality is written in the
OnInvocation method that I've overriden in the
In fact, it does nothing more then checking whether we're in the setter method of the property, and if we are, check whether there exists a lock on the property.
If there exists a lock, we won't allow the property-value to be changed. Otherwise, we just make sure that the implementation of the property itself is called.
The implementation looks like this:
Here, you can see that we use reflection to determine whether we're in the setter-method or in the getter-method of the property; we're only interested if this property is locked if we're about to change the value of the property.
Next, we need to get the name of the property for which we're entering the setter method. This is done via the
GetPropertyForSetterMethod method which uses reflection as well to get the
PropertyInfo object for the given setter-method.
Once this has been done, I can use the
IsLocked method to check whether this property is locked or not.
Note that I haven't checked whether the conversion from
ILockable has succeeded or not. More on that later ...
When the property is locked, I call the
OnAttemptToModifyLockedProperty method (which is declared in
ILockable), and which just raises the
LockedPropertyChangeAttempt event (also declared in the
ILockable interface). By doing so, the programmer can decide what should happen when someone / something attempts to change a locked property. This gives a bit more control to the programmer and is much more flexible then throwing an exception.
When the property is not locked, we let the setter-method execute.
With the creation of this aspect, our third test finally gives a green bar.
Compile time Validation
As I've said a bit earlier, I haven't checked in the
OnInvocation method whether the Target really implemented the
ILockable interface before I called methods of the
The reason for this , is quite simple: the
OnMethodInvocationAspect class has a method
CompileTimeValidate which you can override to add compile-time validation logic (hm, obvious).
I made use of this to check whether the types where I've applied the
Lockable attribute really are
Note that it should be possible to make this code more concise, but I could not just call
method.DeclaringType.GetInterface("ILockable")since that gave a
NotImplementedExceptionwhile compiling. Strange, but true
Now, when I use the
Lockable attribute on a type which is not
ILockable, I'll get the following compiler errors:
Pretty neat, huh ?
Now, what's left is a way to persist the locks in a datastore, but that will be a story for some other time ...