As part of my demonstration for the NYC .NET Meetup in the next couple of days, I prepared some material to show how to use Mono.Cecil to manually weave IL as a post-build step. It solves the problem of what I call “WPF Verbosity Hell”: the thing that makes your eyes bleed and makes God kill a kitten every time you declare a new property.
Since notifypropertyweaver already exists, I figured I’d release the other side of the coin, dependencypropertyweaver. I just pushed my changes onto GitHub.
There are a couple of reasons to use dependency properties rather than regular properties with INotifyPropertyChanged. If you’re using WPF they make more sense because they perform faster and they give you a lot of extra bells and whistles for free. However, the INPC route tends to be more popular because it doesn’t bring in the dependency of WPF.
IL post-build weaving solves the dependency problem because you can selectively choose to weave only the assemblies that get deployed with WPF, and you could even weave INPC into your service layer, and DPs into your client layer. That’s the power of post-build processes.
While this little project initially started out as a simple demonstration of using Mono.Cecil to perform low-level aspect oriented principles, it didn’t take much more work to tidy things up and make it ‘releasable’ into the wild, so I did just that, and open sourced it.
The concept is simple. You take something like this:
public class Student{public string Name { get; set; }public int Age { get; set; }}
And DependencyPropertyWeaver will turn it into this:
public class Student : DependencyObject{public static readonly DependencyProperty NameDependencyProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student));public static readonly DependencyProperty AgeDependencyProperty = DependencyProperty.Register("Age", typeof(int), typeof(Student));public string Name{[CompilerGenerated]get
{return (string)base.GetValue(Student.NameDependencyProperty);}[CompilerGenerated]set
{base.SetValue(Student.NameDependencyProperty, value);}}public int Age{[CompilerGenerated]get
{return (int)base.GetValue(Student.AgeDependencyProperty);}[CompilerGenerated]set
{base.SetValue(Student.AgeDependencyProperty, value);}}}
Even though the class initially didn’t inherit from DependencyObject, the weaved version does. It will also continually go up the inheritance chain until it finds the abstract base class, and makes that inherit from DependencyObject.
Next on the list is obviously documentation (what open source project doesn’t need more documentation?!), however, I think I can slack off on this one since the core library is only 200-300 lines of code :-)
2 comments:
Awesome, I've just started working on my first c# job after 10 years of Java, so learning all this byte code manipulation again! Would it be possible to use annotations to determine if a class and its properties should or shouldn't be processed to create the dependancy properties?
Welcome to the world of C# :) In C#, they are called attributes rather than annotations. The MSBuild task has a property named AttributePatternMatch, which is a regular expression to match on the name of the attribute you want to use to determine whether to weave a property or not.
Keep in mind that the code is highly experimental. Hope that helps!
Post a Comment