Monday 28 September 2009

Book Review – The Art of Unit Testing (Roy Osherove)

In this book, Roy Osherove gives a comprehensive introduction to unit testing. He explains why you would want unit tests in the first place, how to go about writing and running them, as well as addressing some of the challenges involved in introducing unit testing to projects or development teams.

Those who have experience writing unit tests might not find a lot of new material in this book, but it is still worth skimming through as he often provides several ways of achieving a goal, one of which you may not have thought of.

Part 1 introduces unit tests and their benefits, and explains how they differ from integration tests. This elementary distinction is an important one as when many developers initially try to write their first unit tests, they actually write integration tests, ending up with tests that are fragile, unrepeatable and slow, and potentially putting them off from writing any more.

Part 2 explains how mocks and stubs can be used to enable automated testing. He shows that you can make classes testable using several techniques, not just passing in interfaces for all dependencies. He introduces a few of the most popular mocking frameworks.

Part 3 deals with the problem of managing and maintaining all your unit tests. He advocates continuous integration, keeping the tests simple, and presents a useful list of unit testing anti-patterns.

Part 4 tackles some of the tricky issues of introducing unit testing into a legacy codebase, or into a development team that is resistant to change. Osherove is a pragmatist rather than a purist. He recognizes that you may have to start very small, and prove that the time taken to write the tests is worth it.

Two appendices provide useful additional information on some of the OO design principles that make for testable code as well as summarising many of the open source and commercial unit testing tools and frameworks available. This is a very helpful resource, as it helps newcomers to navigate their way through the bewildering array of choices as well as highlighting some new tools that I hadn’t come across.

Overall I would say this is an excellent book to pass round developers in a team that is considering using unit testing or is new to the practice. Doubtless some will be disappointed that he doesn’t stridently demand that TDD is used exclusively, but his honest realism is refreshing and may even prove more effective in winning over new converts to test driven development.

Styling a WPF Volume Meter

In WPF, the complete separation of behaviour from appearance means that you can take a control such as the ProgressBar, and style it to look like any kind of meter. For a recent project, I wanted to make a audio volume meter. The look I wanted was a gradient bar, starting with green for low volumes and going to red for the highest volume:

wpf-volume-meter-1

When the volume is at half way, the progress bar should just show the left hand portion of the gradient:

wpf-volume-meter-2

Styling a ProgressBar in WPF is actually very easy. You can start with the very helpful “Simple Style” template that comes with kaxaml. You simply need to define the visuals for two parts, called PART_Track and PART_Indicator. The first is the background, while the second is the part that dynamically changes size as the current value changes.

At first it would seem trivial to create the look I am after – just create two rectangles on top of each other. The trouble is, that I only want the whole gradient to appear if the value is at maximum. Here’s it incorrectly drawing the entire gradient when the volume is low:

wpf-volume-meter-3

To work around this, I painted the entire gradient on the PART_Track. Then the PART_Indicator was made transparent. This required one further rectangle to cover up the part of the background gradient that I don’t want. I do this with a DockPanel. This allows the PART_Indicator to use its required space, while the masking rectangle fills up the remaining space on the right-hand side, covering up the background gradient.

<style targettype="{x:Type ProgressBar}" x:key="{x:Type ProgressBar}">
  <setter property="Template">
    <setter.value>
      <controltemplate targettype="{x:Type ProgressBar}">
        <grid minheight="14" minwidth="200">
          <rectangle name="PART_Track" stroke="#888888" strokethickness="1">
            <rectangle.fill>
              <lineargradientbrush startpoint="0,0" endpoint="1,0">
                <gradientstop offset="0" color="#FF00FF00"/>
                <gradientstop offset="0.9" color="#FFFFFF00"/>
                <gradientstop offset="1" color="#FFFF0000"/>
              </lineargradientbrush>
            </rectangle.fill>
          </rectangle>
          <dockpanel margin="1">
            <rectangle name="PART_Indicator">
            </rectangle>
            <rectangle name="Mask" minwidth="{TemplateBinding Width}" fill="#C0C0C0"/>
          </dockpanel>
        </grid>
      </controltemplate>
    </setter.value>
  </setter>
</style>

I think there may be an even better way to solve this using a VisualBrush, but I can’t quite get it working at the moment. I’ll post with the solution once I’ve worked it out.

Saturday 26 September 2009

Trimming a WAV file using NAudio

I’m hoping to write a few brief code snippets to demonstrate various uses of NAudio, to eventually form the basis of an FAQ. This example shows how you can take a WAV file and trim a section out of it. You specify the TimeSpan to remove from the beginning and end, as well as an output WAV file. Please note this will only be reliable with PCM format WAV files.

public static class WavFileUtils
{
    public static void TrimWavFile(string inPath, string outPath, TimeSpan cutFromStart, TimeSpan cutFromEnd)
    {
        using (WaveFileReader reader = new WaveFileReader(inPath))
        {
            using (WaveFileWriter writer = new WaveFileWriter(outPath, reader.WaveFormat))
            {
                int bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond / 1000;

                int startPos = (int)cutFromStart.TotalMilliseconds * bytesPerMillisecond;
                startPos = startPos - startPos % reader.WaveFormat.BlockAlign;

                int endBytes = (int)cutFromEnd.TotalMilliseconds * bytesPerMillisecond;
                endBytes = endBytes - endBytes % reader.WaveFormat.BlockAlign;
                int endPos = (int)reader.Length - endBytes; 

                TrimWavFile(reader, writer, startPos, endPos);
            }
        }
    }

    private static void TrimWavFile(WaveFileReader reader, WaveFileWriter writer, int startPos, int endPos)
    {
        reader.Position = startPos;
        byte[] buffer = new byte[1024];
        while (reader.Position < endPos)
        {
            int bytesRequired = (int)(endPos - reader.Position);
            if (bytesRequired > 0)
            {
                int bytesToRead = Math.Min(bytesRequired, buffer.Length);
                int bytesRead = reader.Read(buffer, 0, bytesToRead);
                if (bytesRead > 0)
                {
                    writer.WriteData(buffer, 0, bytesRead);
                }
            }
        }
    }
}

Friday 25 September 2009

Circular WPF Button Template

Here’s another WPF button template, since my first one continues to be one of the most popular posts on my blog. This one is in response to a question about how the button could be made circular. The basic background of the button is formed by superimposing three circles on top of each other:

<Grid Width="100" Height="100" Margin="5">
   <Ellipse Fill="#FF6DB4EF"/>
   <Ellipse>
      <Ellipse.Fill>
         <RadialGradientBrush>
            <GradientStop Offset="0" Color="#00000000"/>
            <GradientStop Offset="0.88" Color="#00000000"/>
            <GradientStop Offset="1" Color="#80000000"/>
         </RadialGradientBrush>
      </Ellipse.Fill>
   </Ellipse>
   <Ellipse Margin="10">
      <Ellipse.Fill>
         <LinearGradientBrush>
            <GradientStop Offset="0" Color="#50FFFFFF"/>
            <GradientStop Offset="0.5" Color="#00FFFFFF"/>
            <GradientStop Offset="1" Color="#50FFFFFF"/>
         </LinearGradientBrush>
      </Ellipse.Fill>
   </Ellipse>
</Grid>

Here’s what that looks like:

Circular Button

Now to turn it into a template, we follow a very similar process to before. We allow the Background colour to be overriden by the user if required. I couldn’t come up with a neat way of forcing the button to be circular, but it is not too much of a chore to set the Height and Width in XAML.

The focus rectangle has been made circular. For the IsPressed effect, I simply change the angle of the linear gradient of the inner circle a little, and move the ContentPresenter down a bit, which seems to work OK. I haven’t created any triggers yet for IsMouseOver, IsEnabled or IsFocused, mainly because I’m not quite sure what would create a the right visual effect.

<Page.Resources>
  <Style x:Key="MyFocusVisual">
     <Setter Property="Control.Template">
        <Setter.Value>
           <ControlTemplate TargetType="{x:Type Control}">
              <Grid Margin="8">
                 <Ellipse
                    Name="r1"
                    Stroke="Black"
                    StrokeDashArray="2 2"
                    StrokeThickness="1"/>
                 <Border
                    Name="border"
                    Width="{TemplateBinding ActualWidth}"
                    Height="{TemplateBinding ActualHeight}"
                    BorderThickness="1"
                    CornerRadius="2"/>
              </Grid>
           </ControlTemplate>
        </Setter.Value>
     </Setter>
  </Style>
  <Style x:Key="CircleButton" TargetType="Button">
     <Setter Property="OverridesDefaultStyle" Value="True"/>
     <Setter Property="Margin" Value="2"/>
     <Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisual}"/>
     <Setter Property="Background" Value="#FF6DB4EF"/>
     <Setter Property="Template">
        <Setter.Value>
           <ControlTemplate TargetType="Button">
              <Grid>
                 <Ellipse Fill="{TemplateBinding Background}"/>
                 <Ellipse>
                    <Ellipse.Fill>
                       <RadialGradientBrush>
                          <GradientStop Offset="0" Color="#00000000"/>
                          <GradientStop Offset="0.88" Color="#00000000"/>
                          <GradientStop Offset="1" Color="#80000000"/>
                       </RadialGradientBrush>
                    </Ellipse.Fill>
                 </Ellipse>
                 <Ellipse Margin="10" x:Name="highlightCircle" >
                    <Ellipse.Fill >
                       <LinearGradientBrush >
                          <GradientStop Offset="0" Color="#50FFFFFF"/>
                          <GradientStop Offset="0.5" Color="#00FFFFFF"/>
                          <GradientStop Offset="1" Color="#50FFFFFF"/>
                       </LinearGradientBrush>
                    </Ellipse.Fill>
                 </Ellipse>
                 <ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center"/>
              </Grid>
              <ControlTemplate.Triggers>
                 <Trigger Property="IsPressed" Value="True">
                    <Setter TargetName="highlightCircle" Property="Fill">
                       <Setter.Value>
                       <LinearGradientBrush StartPoint="0.3,0" EndPoint="0.7,1">
                          <GradientStop Offset="0" Color="#50FFFFFF"/>
                          <GradientStop Offset="0.5" Color="#00FFFFFF"/>
                          <GradientStop Offset="1" Color="#50FFFFFF"/>
                       </LinearGradientBrush>
                       </Setter.Value>
                    </Setter>
                    <Setter TargetName="content" Property="RenderTransform">
                       <Setter.Value>
                          <TranslateTransform Y="0.5" X="0.5"/>
                       </Setter.Value>
                    </Setter>
                 </Trigger>
              </ControlTemplate.Triggers>
           </ControlTemplate>
        </Setter.Value>
     </Setter>
  </Style>
</Page.Resources>

Here’s how we declare a few of these buttons of different sizes, and with different background colours:

<WrapPanel>
  <Button Width="100" Height="100" Style="{StaticResource CircleButton}">Hello World</Button>
  <Button Width="80" Height="80" Style="{StaticResource CircleButton}" Background="#FF9F1014">Button 2</Button>
  <Button Width="80" Height="80" Style="{StaticResource CircleButton}" Background="#FFD8C618">Button 3</Button>      
  <Button Width="80" Height="80" Style="{StaticResource CircleButton}" Background="#FF499E1E">Button 4</Button>
  <Button Width="80" Height="80" Style="{StaticResource CircleButton}" Background="Orange">Button 5</Button>
  <Button Width="80" Height="80" Style="{StaticResource CircleButton}" Background="#FF7C7C7C">Button 6</Button>
  <Button Width="80" Height="80" Style="{StaticResource CircleButton}" Background="Purple" Foreground="White">Button 7</Button>
  <Button Width="100" Height="100" Style="{StaticResource CircleButton}" Background="#FF3120D4" Foreground="White">Button 8</Button>
</WrapPanel>

Circular Buttons

Sadly, the use of ControlTemplate triggers means that this template can’t be used directly in Silverlight. I’ll maybe look into converting them to VisualStates for a future blog post.

Thursday 24 September 2009

Crowd-Sourced Code Reviews

In a post yesterday, I bemoaned the lack of a clean syntax in NUnit for testing whether events fired from an object under test, and set to work at writing my own helper methods. I posted on the NUnit discussion group, to see whether there was a better way. And there was. A really obvious way. Here’s how my tests could have been written without the need for an Assert.Raises function, or for any code outside the test method:
[Test]
public void TestRaisesClosedEvent_Improved()
{
    Blah blah = new Blah();
    EventArgs savedEventArgs = null;
    blah.Closed += (sender, args) => savedEventArgs = args;
    blah.RaiseClosed(1);
    Assert.IsNotNull(savedEventArgs);
}

[Test]
public void TestCanCheckRaisesMany_Improved()
{
    Blah blah = new Blah();
    var savedEvents = new List<openedeventargs>();
    blah.Opened += (sender, args) => savedEvents.Add(args);
    blah.RaiseOpened(5);
    Assert.AreEqual(5, savedEvents.Count);
    Assert.AreEqual("Message 3", savedEvents[2].Message);
}
Of course, I was kicking myself for missing such an obvious solution, but it left me pondering how often this happens without me realising it.
Earlier today Clint Rutkas tweeted:
i feel like i'm doing such bad things in WPF right now
… and I know exactly how he feels. In a couple of WPF applications I am working on, I am trying to use the MVVM pattern. It often ends up with me writing code that might be a really cool piece of lateral thinking, or it might be a pointlessly overcomplicated hack. For an example, here’s an  attached dependency property (usage here) I created to let me bind to Storyboard completed events.
What I need is another person to look over my shoulder and tell me whether I am missing the obvious, unaware of an API, or ignorant of a best practice. But all too often, that person doesn’t exist.
In a commercial environment, hopefully there is at least some kind of provision for code reviews to take place, or maybe even pair programming. But what about the lone programmer working on open source projects?
Maybe we need some way to “crowd-source” code reviews. Some way of getting lots of eyes on your source code, even if it is only for a couple of minutes, and an easy way of getting hold of that feedback. A bit like fivesecondtest but where you help out an open source developer by code reviewing a changeset. I’ve asked for this as a feature on CodePlex.
What do you think? Could it work? How do you make sure you’re not missing the obvious in the code you write?

Wednesday 23 September 2009

Asserting events with NUnit

Suppose we want to write unit tests for a class that raises events. We want to check that the right events are raised, the right number are raised, and that they have the correct parameters. Here’s an example of a class that we might want to test:
class Blah
{
    public event EventHandler Closed;
    public event EventHandler<OpenedEventArgs> Opened;

    public void RaiseClosed(int count)
    {
        for(int n = 0; n < count; n++)
        {
            Closed(this, EventArgs.Empty);
        }
    }

    public void RaiseOpened(int count)
    {
        for(int n = 0; n < count; n++)
        {
            Opened(this, new OpenedEventArgs() { Message = String.Format("Message {0}", n + 1) });
        }
    }
}

class OpenedEventArgs : EventArgs
{
    public string Message { get; set; }
}

To write NUnit test cases for this class, I would usually end up writing an event handler, and storing the parameters of the event in a field like follows:
EventArgs blahEventArgs;

[Test]
public void TestRaisesClosedEvent()
{
    Blah blah = new Blah();
    blahEventArgs = null;
    blah.Closed += new EventHandler(blah_Closed);
    blah.RaiseClosed(1);
    Assert.IsNotNull(blahEventArgs);
}

void blah_Closed(object sender, EventArgs e)
{
    blahEventArgs = e;
}
While this approach works, it doesn’t feel quite right to me. It is fragile – forget to set blahEventArgs back to null and you inadvertently break other tests. I was left wondering what it would take to create an Assert.Raises method that removed the need for a private variable and method for handling the event.
My ideal syntax would be the following:
Blah blah = new Blah();
var args = Assert.Raises<OpenedEventArgs>(blah.Opened, () => blah.RaiseOpened(1));
Assert.AreEqual("Message 1", args.Message);

The trouble is, you can’t specify “blah.Opened” as a parameter – this will cause a compile error. So I have to settle for second best and pass the object that raises the event, and the name of the event. So here’s my attempt at creating Assert.Raise, plus an Assert.RaisesMany method that allows you to see how many were raised and examine the EventArgs for each one:
public static EventArgs Raises(object raiser, string eventName, Action function)
{
    return Raises<EventArgs>(raiser, eventName, function);
}

public static T Raises<T>(object raiser, string eventName, Action function) where T:EventArgs
{
    var listener = new EventListener<T>(raiser, eventName);
    function.Invoke();
    Assert.AreEqual(1, listener.SavedArgs.Count);
    return listener.SavedArgs[0];
}

public static IList<T> RaisesMany<T>(object raiser, string eventName, Action function) where T : EventArgs
{
    var listener = new EventListener<T>(raiser, eventName);
    function.Invoke();
    return listener.SavedArgs;
}

class EventListener<T> where T : EventArgs
{
    private List<T> savedArgs = new List<T>();

    public EventListener(object raiser, string eventName)
    {
        EventInfo eventInfo = raiser.GetType().GetEvent(eventName);
        var handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, "EventHandler");
        eventInfo.AddEventHandler(raiser, handler);            
    }

    private void EventHandler(object sender, T args)
    {
        savedArgs.Add(args);
    }

    public IList<T> SavedArgs { get { return savedArgs; } }
}
This allows us to dispense with the private field and event handler method in our test cases, and have nice clean test code:
[Test]
public void TestCanCheckRaisesEventArgs()
{
    Blah blah = new Blah();
    AssertExtensions.Raises(blah, "Closed", () => blah.RaiseClosed(1));
}

[Test]
public void TestCanCheckRaisesGenericEventArgs()
{
    Blah blah = new Blah();
    var args = AssertExtensions.Raises<OpenedEventArgs>(blah, "Opened", () => blah.RaiseOpened(1));
    Assert.AreEqual("Message 1", args.Message);
}

[Test]
public void TestCanCheckRaisesMany()
{
    Blah blah = new Blah();
    var args = AssertExtensions.RaisesMany<OpenedEventArgs>(blah, "Opened", () => blah.RaiseOpened(5));
    Assert.AreEqual(5, args.Count);
    Assert.AreEqual("Message 3", args[2].Message);
}

There are a couple of non-optimal features to this solution:
  • Having to specify the event name as a string is ugly, but there doesn’t seem to be a clean way of doing this.
  • It expects that your events are all of type EventHandler or EventHandler<T>. Any other delegate won’t work.
  • It throws away the sender parameter, but you might want to test this.
  • You can only test on one particular event being raised in a single test (e.g. can’t test that a function raises both the Opened and Closed events), but this may not be a bad thing as tests are not really supposed to assert more than one thing.
I would be interested to know if anyone has a better way of testing that objects raise events. Am I missing a trick here? Any suggestions for how I can make my Raises function even better?
Download full source code here

Tuesday 15 September 2009

Checking MIME type for cross domain Silverlight hosting

I recently ran into some problems trying to embed a Silverlight application in a web page hosted on another server. It seems that to do so, you must have your MIME type for .xap files correctly configured (should be application/x-silverlight-app). Interestingly, this is not required if you are hosting the .xap file in a web page on the same domain.

Unfortunately for me, my shared Linux hosting provider allows no way of configuring or even viewing the MIME types. After searching in vain for a utility that would let me have a look and see what MIME type a given URL was returning, I wrote my own test function. It turns out to be possible in just two lines of code – create a WebRequest, and examine the ContentType of the WebResponse.

[TestFixture]
public class MimeTypeChecker
{
    [Test]
    public void CheckSilverlightMimeTypeIsCorrect()
    {
        string mimeType = GetMimeType("http://www.mydomain.com/mysilverlightapp.xap");
        Assert.AreEqual("application/x-silverlight-app", mimeType);
    }

    public string GetMimeType(string url)
    {
        WebRequest request = WebRequest.Create(url);
        WebResponse response = request.GetResponse();
        return response.ContentType;
    }
}

Update: If your .xap file is hosted on an Apache server on Linux, you can set up the MIME types correctly by creating a .htaccess file. This can be put in the root of your hosting space, or just in the folder containing the .xap file. It only needs the .xap registration, but the example I show below configures xaml and xbap as well:

AddType application/x-silverlight-app .xap
AddType application/xaml+xml .xaml
AddType application/x-ms-xbap .xbap

Monday 14 September 2009

Parameterized Tests with TestCase in NUnit 2.5

For some time, NUnit has had a RowTest attribute in the NUnit.Extensions.dll, but with NUnit 2.5, we have built-in support for parameterized tests. These reduce the verbosity of multiple tests that differ only by a few arguments.

For example, if you had test code like this:

[Test]
public void Adding_1_and_1_should_equal_2()
{
    Assert.AreEqual(2,calculator.Add(1,1));
}

[Test]
public void Adding_1_and_2_should_equal_3()
{
    Assert.AreEqual(3, calculator.Add(1, 2));
}

[Test]
public void Adding_1_and_3_should_equal_4()
{
    Assert.AreEqual(4, calculator.Add(1, 3));
}

You can now simply refactor to:

[TestCase(1, 1, 2)]
[TestCase(1, 2, 3)]
[TestCase(1, 3, 4)]
public void AdditionTest(int a, int b, int expectedResult)
{
    Assert.AreEqual(expectedResult, calculator.Add(a, b));
}

The NUnit GUI handles this very nicely, allowing us to see which one failed, and run them individually:

NUnit Parameterized Tests

TestDriven.NET doesn’t give us the ability to specify an individual test case to run (hopefully a future feature), but it will show us the parameters used for any test failures:

TestCase 'SanityCheck.CalculatorTests.AdditionTest(1,2,3)' failed: 
  Expected: 3
  But was:  2
...\CalculatorTests.cs(19,0): at SanityCheck.CalculatorTests.AdditionTest(Int32 a, Int32 b, Int32 expectedResult)

TestCase 'SanityCheck.CalculatorTests.AdditionTest(1,3,4)' failed: 
  Expected: 4
  But was:  2
...\CalculatorTests.cs(19,0): at SanityCheck.CalculatorTests.AdditionTest(Int32 a, Int32 b, Int32 expectedResult)

Another very cool feature is that you can specify a TestCaseSource function, allowing you to generate test cases on the fly. One way I have used this feature is for some integration tests that examine a folder of legacy test data files and create a test for each file.

There are a few options for how to provide the source data. Here I show using a function that returns an IEnumerable<string>:

[TestCaseSource("GetTestFiles")]
public void ImportXmlTest(string xmlFileName)
{
    xmlImporter.Import(xmlFileName);
}

public IEnumerable<string> GetTestFiles()
{
    return Directory.GetFiles("D:\\Test Data", "*.xml");
}

Now when NUnit loads the test assembly, it runs the GetTestFiles function, to get the test case parameters, allowing you to run them individually if necessary.

TestCaseSource Function

There is one gotcha. If your TestCaseSource function takes a long time to run, you will need to wait every time NUnit (or TestDriven.NET) reloads your unit test DLL. So my example of examining a directory for files could negatively impact performance if there are too many test cases (I discovered this after loading 14000 test cases from a network drive).

Friday 11 September 2009

Coding Dojo

I went to my first “coding dojo” last night, which was also the first one run to be run in Southampton by Tom Quinn. You can read about what a coding dojo is here, but the basic idea is that a group of people collaboratively work on solving a basic programming problem, using TDD. To ensure everyone participates, developers are paired and work together for five minutes, before one leaves the pair and another joins.

The task we attempted was to create a calculator that worked with Roman numerals. We started by listing some tests we wanted to pass. This I think was a good way to start, but we actually made very little progress in the first round of coding. Perhaps it was partly the awkwardness of coding in front of a group – fear of looking stupid, or fear of looking like a show-off - so no one was initially willing to stamp their own design onto the problem. The second time round the table it was a different story, with people eager to get the keyboard to implement their ideas.

The other real problem was that we didn’t agree our overall approach to the problem. This was silly, because it was clear that we were going to have to make something to convert Roman numerals to integers, and something to convert integers back to Roman numerals. But because we hadn’t agreed that, we started off making the tests pass with hard coded results.

It meant we ended up with 7 or 8 tests for the top-level object – the calculator, when really we needed some lower-level tests for Roman numeral conversion. It highlighted a TDD anti-pattern: doing “the simplest thing that could make the test pass” should not mean, “hard code return values for all the test cases”. If you do that, you may have passing tests but you are no closer to solving your problem.

Positives: It was good to see everyone getting involved, and the idea of pairing worked well. It was also interesting to see how different people tackled the same problem.

Suggestions: Perhaps enforce the “red-green-refactor” rule a bit more, so that the there is more focus on getting a single test passing before you hand on, and more emphasis on refactoring, rather than just passing tests. Five minutes is surprisingly short, and lots of pairs had to take over with the code in a non-compiling, non-working state. You could perhaps increase the timeslot to 7 minutes, although if there are more than 7 or 8 people present, you would be hard pressed to go twice round the room in a two hour meeting. If you had 10 or more people, it might make sense to break into two groups.

Monday 7 September 2009

Custom Object Factory Unity Extension

Suppose you have an object that cannot be directly created by your IoC container. In my case, it is because that object is a .NET remoting object, so it must be created on a different computer.

One way to solve this would be to register a factory that creates your object. But in my application, there are dozens of objects that need to be created in this special way, and they all inherit from a common base interface. Ideally, I would like it to be completely transparent, so I request the type I want, and the container works out that it needs to be built in a special way.

So I set about making a Unity extension, which would allow me to intercept Resolve requests for certain interfaces, and create them using my custom factory method, or return the ones already cached.

The way to accomplish this is to create a Build Strategy, which checks to see if the requested type meets our criteria. If it does, we have a look to see if we have already cached and constructed the object. If not, we call our factory method to construct it, and cache the result. One important thing to notice is that I pass the “Context” from the extension into the build strategy. That is so that if you call Resolve from a child container, it will return the same instance as if you called it from a different child container. Obviously, your requirements may differ.

The if statement in PreBuildUp contains my rule for deciding if this is a Resolve request I want to intercept. Again, this could be customised for any arbitrary logic.

public class FactoryMethodUnityExtension<T> : UnityContainerExtension
{
    private Func<Type,T> factory;

    public FactoryMethodUnityExtension(Func<Type,T> factory)
    {
        this.factory = factory;
    }

    protected override void Initialize()
    {
        var strategy = new CustomFactoryBuildStrategy<T>(factory, Context);

        Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);            
    }
}

public class CustomFactoryBuildStrategy<T> : BuilderStrategy
{
    private Func<Type,T> factory;
    private ExtensionContext baseContext;

    public CustomFactoryBuildStrategy(Func<Type,T> factory, ExtensionContext baseContext)
    {
        this.factory = factory;
        this.baseContext = baseContext;
    }

    public override void PreBuildUp(IBuilderContext context)
    {
        var key = (NamedTypeBuildKey)context.OriginalBuildKey;

        if (key.Type.IsInterface && typeof(T).IsAssignableFrom(key.Type))
        {
            object existing = baseContext.Locator.Get(key.Type);
            if (existing == null)
            {
                // create it
                context.Existing = factory(key.Type);
                
                // cache it
                baseContext.Locator.Add(key.Type, context.Existing);
            }
            else
            {
                context.Existing = existing;
            }
        }
    }
}

Using the extension is very simple. Simply give it the delegate to use to create the objects, and register it as an extension:

WhateverFactory factory = new WhateverFactory();
container = new UnityContainer();
container.AddExtension(new FactoryMethodUnityExtension<IWhatever>(factory.Create));

Here’s a couple of blog posts I found helpful while trying to learn how to create a Unity extension: