C# offers many features of the functional languages. One of them is the Extension Methods. This fantastic feature allows solving some non-trivial problems in very elegant ways.
However, I always felt that the type extensibility model was not complete without Extension Properties. Apparently, I am not alone. Now and then, I see the articles/solutions for mimicking Extension Properties. Initially, I thought that Microsoft would eventually deliver a proper Extension Properties implementation but now it is apparent that it's very unlikely.
To be technically accurate, XAML Attached Properties allows extending types with the property-like dynamic "members". However, the Attached Properties implementation is relatively heavy, too XAML specific and the usage pattern isn't so great neither.
Thus the presented solution is an attempt to implement generic Attached Properties based on the extension methods syntax.
While hoping for a proper solution from Microsoft, I developed and used my own, which achieves the desired behavior. Though it is lacking the syntactical sugar possible only by truly extending the C# syntax, it served me very well and I decided to share it.
The trigger for this article was another article on the very same subject:
It is a very good solid article. The author got my 5. He explained very well the objective he was trying to achieve and provided a robust working solution for the problem. However, I felt that his solution was a bit over engineered and practically the same behavior could be achieved with a much simpler implementation.
How It Works
The solution is straight forward. It is built around the
dictionary, which associates the instance of an object with a collection of the named values (key/pair). The dictionary is hosted by the
static class, which allows setting and getting named values to the instance of the object via Extension Methods:
static class AttachedProperies
public static Dictionary<WeakReference, Dictionary<string, WeakReference>> ObjectCache;
public static void SetValue<T>(this T obj, string name, object value)...
public static T GetValue<T>(this object obj, string name)...
ObjectCache references the objects with
WeakReferences for avoiding memory leaks. The name of the class (
AttachedProperties) is deliberate as it mimics the XAML Attached Properties. The API relies on extension methods so the usage pattern can be as simple as follows:
var animation = (Storyboard)FindResource("Storyboard1");
void OnStoryboard_Complete(object sender,....)
var animation = (Storyboard)sender;
DateTime startTime = animation.GetValue<DateTime>("StartTime");
Of course, using
string literals isn't the cleanest approach. Thus, I would recommend to group properties by the target type in the
static classes containing extension methods. This allows strongly typed and readable syntax:
static class StoryboardExtensions
public static DateTime GetStartTime(this Storyboard obj)
public static void SetStartTime(this Storyboard obj, DateTime value)
And the usage:
DateTime startTime = animation.GetStartTime();
The solution also solves an interesting problem - collecting the weak references to the already disposed objects. The routine which does this is the
Collect is to be invoked either explicitly or automatically depending on the
Collect will be called automatically every time when number of the "weakly-referenced" instances doubles (since the last
Collect will be called automatically when Garbage Collector collects unreferenced resources.
Collect will be called automatically with every
Collect will be called explicitly from the host code.
That is it! This is roughly all about the solution. The source code can be found in the article downloadables (AttachedProperties_original.cs).
The presented solution despite some conceptual similarities has significant differences comparing to the other solution I mentioned in the introduction:
- The implementation is much leaner (~150 lines of code).
- The timer based garbage collection mechanism present in the alternative solution seems too simplistic to me. So I have implemented the event driven collection mechanism.
- The presented solution deliberately does not offer any discovery mechanism. In my opinion, using the
TypeDesciptorProvider in the alternative solution does not really bring any practical value. Thus I decided not to invest in this feature.
Revising the Solution
My original implementation was based on the
WeakReference dictionary. However in .NET 4.0, there is a more suitable collection type for this -
ConditionalWeakTable. This class is capable of fully automatic removal of all references to the instances no longer referenced anywhere else. Because there is no need for any memory management any more, the whole solution can be collapsed to the ~30 lines of code. The following is the final revised solution:
public static class AttachedProperies
public static ConditionalWeakTable<object,
Dictionary<string, object>> ObjectCache = new ConditionalWeakTable<object,
public static void SetValue<T>(this T obj, string name, object value) where T : class
Dictionary<string, object> properties = ObjectCache.GetOrCreateValue(obj);
properties[name] = value;
public static T GetValue<T>(this object obj, string name)
Dictionary<string, object> properties;
if (ObjectCache.TryGetValue(obj, out properties) && properties.ContainsKey(name))
public static object GetValue(this object obj, string name)
At the time of the first implementation, I was not aware of
ConditionalWeakTable so I used a
dictionary. This decision required me to solve the memory management challenges. Because the original solution demonstrates some interesting techniques, I decided to include it into downloadables anyway (AttachedProperties_original.cs).
Also, the original solution can be used under early versions of CLR (except for the GC events). However, if your target platform is .NET 4.0, then you should use the
ConditionalWeakTable based solution (AttachedProperties.cs). It is simpler, better with the memory management and well... did I mention it is simpler?
It is important to be aware of the limitations of the presented solution:
ConditionalWeakTable based solution can only be run on .NET v4.0.
ConditionalWeakTable based solution cannot be extended to support any sort of discovery mechanism. The reason for this is that
ConditionalWeakTable does not support any browsing API as
- Support for value types as instances to attach the values to is problematic. This is a common limitation for all solutions of this sort.
Points of Interest
The generic Attached Properties is a great "assistance feature" for implementing loosely coupled architecture. They also allow bringing (when required) the stateful nature to the otherwise stateless extensibility model offered by Extension Methods. Which in turn brings Extension Methods up to the level when it is possible to implement what I would call "Safe Multiple Inheritance" in C# . Though it is another topic for discussion...