bling.github.io

This blog has relocated to bling.github.io.

Sunday, April 17, 2011

Integrating DependencyPropertyWeaver Into Your Build

See the introduction here.

The MSBuild task as it stands currently by default will attempt to weave everything that it finds.  This is probably not optimal in most use cases, but any changes is a simple modification to the LINQ query in the code.  For now, it’s only available in source format since there are bound to be bugs here and there, and once those get ironed out it’ll be easier to release a “point something” release.

An example of how its used can be seen in the unit tests, in the project DependencyPropertyWeaver.Tests.Models.  If you open it up in your favorite text editor, you will see this crucial line:

<Target Name="AfterBuild">
    <Exec Command="C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe postbuild.proj /p:Files=DependencyPropertyWeaver.Tests.Models.dll" WorkingDirectory="$(OutputPath)" />
  </Target>

And the contents of postbuild.proj is simply this:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Weave" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="DependencyPropertyWeaver.DependencyPropertyWeaverTask"
             AssemblyFile="DependencyPropertyWeaver.dll" />
  <Target Name="Weave">
    <ItemGroup>
      <Input Include="$(Files)" />
    </ItemGroup>
    <DependencyPropertyWeaverTask Files="@(Input)" />
  </Target>
</Project>

The AfterBuild target is a special target with MSBuild, which, as the name implies, will run after the target has been built.  In this case, after the project is completed, it will invoke another MSBuild instance to perform the weaving.  Invoking a new MSBuild process is required because the <UsingTask> will load the assembly into the current AppDomain, and once loaded it cannot be unloaded.

If you don’t mind the unloading part, you can simply add the <UsingTask> directly into the project file and invoked the <DependencyPropertyWeaverTask> there, and avoid the hassle of having a separate file.

Currently, the DependencyPropertyWeaverTask supports the TypePatternMatch and AttributePatternMatch, which as the names imply will use regular expression filtering on type names or properties with the attribute you want to weave.  If these properties are null, they are ignored.

Next on the feature list is weaving attached properties ;-)

Friday, April 15, 2011

Introducing DependencyPropertyWeaver

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 :-)