I’ve been intrigued with PostSharp for some time. PostSharp is an AOP platform and works its magic at build time (for the most part). You apply an aspect and PostSharp does the IL weaving, via integration with MSBuild, to output an assembly with the injected functionality. The goal, as their home page banner says: “Eradicate boilerplate. Raise abstraction. Enforce good design.”
I worked on the DevForce framework for a number of years and we’d written several custom aspects to implement certain product features, but I’d never had a chance to play with some of the “ready-made” implementations in the PostSharp patterns library. Writing your own aspects can range from fairly easy to quite hard, but many of the out-of-the-box aspects in the patterns library seem to combine great functionality and ease of use. Of particular interest to me are the ready-made patterns for INotifyPropertyChanged
support and threading. The patterns library also includes support for logging, exception handling and a few other patterns, but I’ll save those for another day.
To get started with PostSharp, install the package(s) from NuGet. You’ll also be prompted for license information during the install, but since I’m using the 3.2 alpha I signed up for a 45 day free trial of PostSharp Ultimate.
NotifyPropertyChanged
Nothing screams boilerplate more than INotifyPropertyChanged
. In any .NET environment, data bound objects must implement INotifyPropertyChanged
(or the PropertyChanged
pattern) for changes to be seen by UI controls. This means raising the PropertyChanged
event, and more importantly, losing the simplicity of automatic properties since property setters must raise PropertyChanged
. This gets irritating quickly.
With PostSharp, the solution is simple: just decorate the class with the NotifyPropertyChanged
aspect, found in the Model Pattern Library.
You can decorate a base class too, and get the functionality you expect across its sub-types. If you’ve both implemented INotifyPropertyChanged
and added the aspect (maybe in a complex inheritance hierarchy), PostSharp handles that too. PostSharp will add the PropertyChanged
logic to the setters of all public
properties, but you can opt-out too by decorating a property with the IgnoreAutoChangeNotification
aspect.
Here’s a simple class and sub-class with full INotifyPropertyChanged
functionality:
[NotifyPropertyChanged]
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get { return string.Format("{0} {1}", FirstName, LastName); }
}
[IgnoreAutoChangeNotification]
public DateTime LastContactDate { get; set; }
}
public class GoldCustomer : Customer
{
public int Points { get; set; }
}
Under the hood, the aspect will inject the INotifyPropertyChanged
logic into your IL. Actually, it implements a PostSharp interface called INotifyChildPropertyChanged
, which in turn extends INotifyPropertyChanged
.
This simplicity does come with a performance penalty, however. In my tests setting a single string
property on a class implementing INotifyPropertyChanged
(INPC) versus one using the NotifyPropertyChanged
aspect, the INPC implementation was about 100x faster. So, while the aspect is a great solution for eliminating the boilerplate, for classes which won’t be data bound in the UI or which have strict performance requirements, it’s not an ideal solution.
Threading
The PostSharp Threading Pattern Library contains several interesting aspects, with more coming in the 3.2 release.
Background and Dispatched
The Background
aspect can be applied to any method to dispatch it to the background. Under the hood, PostSharp does a Task.Start
to invoke your method on a background thread. With the async
/await
support in .NET 4.5, this may not be all that handy, but if you’re using a BackgroundWorker
or working directly with the Thread
or ThreadPool
classes, it may make your code a bit cleaner. Likewise, the Dispatched
aspect will ensure the decorated method is invoked on the UI thread. Background
and Dispatched
don’t need to be used together, and using Dispatched
can clean up some ugly BeginInvoke
logic.
Coincidentally, I was just reading the April issue of MSDN Magazine and Laurent Bugnion’s article Multithreading and Dispatching in MVVM Applications, so switched his simple non-MVVM starting solution to use Background
and Dispatched
. Bugnion uses the DispatchHelper
from MvvmLight
in his MVVM samples; you can use these PostSharp aspects in your view models too, but unlike some of the other PostSharp libraries which have portable class library support, the threading library is available for .NET 4 and above only.
Here’s a snippet of the sample code from the article using Background
and Dispatched
:
[Background]
private void StartSuccessClick(object sender, RoutedEventArgs e)
{
var loopIndex = 0;
while (_condition)
{
UpdateStatus(string.Format("Loop # {0}", loopIndex++));
Thread.Sleep(500);
}
}
[Dispatched]
private void UpdateStatus(string msg)
{
StatusTextBlock.Text = msg;
}
These are handy but not all that compelling, since an InvalidOperationException
is thrown immediately when you try to access a UI control on a background thread, and therefore easy to diagnose and fix. Much more insidious are thread safety problems. In a multi-threaded environment, safely working with mutable objects can be challenging: thread safety issues generally appear as odd “random” errors and deadlocks, often only under load, and are very difficult to reproduce and debug.
PostSharp defines three threading models or patterns and corresponding aspects: Thread Unsafe, Read-Writer Synchronized and Actor. (I’ll take a look at Actor in a follow-on post.)
ThreadUnsafe
If a single instance of a class should never be accessed concurrently, decorate the class with the ThreadUnsafe
aspect. Should you access the object across concurrent threads, you’ll receive an immediate ConcurrentAccessException
from PostSharp.
Markup is easy:
[ThreadUnsafe]
public class Booking
{
public string CustomerName { get; set; }
public DateTime StartTime { get; set; }
public int NumberOfPersons { get; set; }
}
The ThreadUnsafe
aspect also allows you to set a ThreadUnsafePolicy
, such as ThreadAffine
, which gives thread affinity to your objects and will cause a ThreadMismatchException
to be thrown if the object is used on any thread other than the creating thread. Also baked into ThreadUnsafe
is some compile-time validation and support for opting out to perform your own explicit synchronization.
Most classes aren’t designed to be thread safe, and don’t need to be, but if you have any globally shared objects or need to pass an object around among threads, or alternately, ensure it’s never shared across threads, this aspect is far easier to use than performing your own locking. I didn’t look at performance here, but I’ll take a quick exception over data corruption any day.
ReaderWriterSynchronized
Finally, dealing with thread-safe objects. When you do have objects which truly must be shared in a multi-threaded environment dealing with thread safety can be a big pain. First deciding on whether to use a lock, a mutex, a ReaderWriterLock
, Interlocked variables, etc., and then what the scope should be. Once it’s finally working correctly, a later modification “forgets” to lock the resource, and you don’t discover this until you’re in production under heavy load.
PostSharp handles this declaratively with its ReaderWriterSynchronized
aspect. Under the hood, it’s an implementation of ReaderWriterSynchronizedSlim
, and provides for concurrent reads and exclusive writes. Here, you decorate the class with ReaderWriterSynchronized
, but must also mark methods, getters and setters with either Reader
or Writer
aspects. (Prior to PostSharp 3.2, these aspects were called ReaderLock
and WriterLock
.) The advantage of the aspect, other than the removal of all the locking code, is that PostSharp will immediately detect when a resource is accessed without a lock and throw a LockNotHeldException
.
Here’s an example of the .NET sample for a SynchronizedCache using PostSharp aspects:
[ReaderWriterSynchronized]
public class SynchronizedCache
{
private Dictionary innerCache = new Dictionary();
[Reader]
public string Read(int key)
{
return innerCache[key];
}
[Writer]
public void Add(int key, string value)
{
innerCache.Add(key, value);
}
[UpgradeableReader]
public AddOrUpdateStatus AddOrUpdate(int key, string value)
{
string result = null;
if (innerCache.TryGetValue(key, out result))
{
if (result == value)
{
return AddOrUpdateStatus.Unchanged;
}
else
{
innerCache[key] = value;
return AddOrUpdateStatus.Updated;
}
}
else
{
innerCache.Add(key, value);
return AddOrUpdateStatus.Added;
}
}
[Writer]
public void Delete(int key)
{
innerCache.Remove(key);
}
public enum AddOrUpdateStatus
{
Added,
Updated,
Unchanged
};
}
In part 2, I plan to take a look at PostSharp’s Actor
support, along with the new Recordable
aspect for undo/redo and the Immutable
and Freezable
aspects, available in the upcoming 3.2 release.
CodeProject
Filed under:
C# Tagged:
AOP,
INotifyPropertyChanged,
PostSharp,
Threading
I started my professional career as a mainframe Assembler programmer at a small insurance company. Since then I've developed dozens of enterprise and commercial solutions using a grab bag of technologies. I've been developing with .NET since 2003 and still love it.