Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Wednesday, 17 August 2011

Unit Testing C# Custom Attributes with NUnit Part 4

In Unit Testing C# Custom Attributes with NUnit Part 3 towards the end I showed the following code
Assert.That(MethodBase.GetCurrentMethod(), 
            Has.Attribute<FunkyAttribute>().Property("SettingOne").TypeOf<int>());
to test the type of a property on an attribute.  As it turns out this does not actually do that.  Instead it tests the type of the value returned from the property.  What's happening is that the object returned from Property() isn't some of meta-object representing a property but is the actual value of the property.

In the case above it amounts to the same thing.  As the property type is an int even if it has not been set the value will be 0 of which type is int.  However, if it's a reference type (quite likely a string) or a nullable type the value can be null.  E.g.

Assert.That(MethodBase.GetCurrentMethod(), 
     Has.Attribute<FunkyAttribute>().Property("FunkyName").TypeOf<string>());

 
Which causes the following when run:

AttrTestV3.FunkyTester.TestThatTheTypeOfFunkyNameWhenNotSetIs_string:
  Expected: attribute AttrTestDefs.FunkyAttribute property FunkyName <System.String>
  But was:  <AttrTestDefs.FunkyAttribute>

It seems that when there is no value Property() which tests for the presence of a the specified property name and implicitly returns the value of the property (if found) has nothing to return so for some reason the attribute type obtained from the call Has.Attribute() is returned.

Currently, there is no way with NUnit to handle this case.  I started a thread on the NUnit discussion group which discusses this issue and it seems like the authors of NUnit have some plans.

As an interim solution if the property is optional for a custom attribute then in the fixture make sure a value is assigned.  In the case above:

[Test]
[Funky(FunkyName = "dummy")]
public void TestThatTheTypeOfFunkyNameWhenNotSetIs2_string()
{
    Assert.That(MethodBase.GetCurrentMethod(),
         Has.Attribute<FunkyAttribute>().Property("FunkyName").TypeOf<string>());
}

I think that's the end again:-)  Here are the links to the previous parts: One, two & three.

Tuesday, 26 July 2011

Unit Testing C# Custom Attributes with NUnit Part 3

During Unit Testing C# Custom Attributes with NUnit Part 2 where the Assertions were converted from the Classic to the Constraint model it was simply a process of replacing

Assert.<SomeAssertion>(<object>)

with

Assert.That(<object>, Is.<SomeAssertion>)

The key thing being the 'Is' object that houses all the original assertions used.  Whilst doing this I came across the 'Has' object.  This doesn't appear in the documentation until about halfway when collections are covered.  Not mentioned at all in the documentation is the method Has.Attribute<AttributeType> which tests whether an attribute (custom or otherwise) is present on the object being tested.   For the current method this is simply:

Assert.That(MethodBase.GetCurrentMethod(), Has.Attribute<FunkyAttribute>());

Even better, having obtained the Attribute (if not present the assertion will fail) it too can be tested.  The important aspect here is that it contains a specific property which can easily be tested in the same statement by appending '.Property(<PropertyName>)' in a Fluent style to give:

Assert.That(MethodBase.GetCurrentMethod(), Has.Attribute<FunkyAttribute>().Property("FunkyName"));

The next is to test whether this property contains the correct value.  This can be obtained in a similar way by further appending '.EqualTo(<SomeValue>)' to give:

Assert.That(MethodBase.GetCurrentMethod(), Has.Attribute<FunkyAttribute>().Property("FunkyName").EqualTo("RipSnorter"));

In a single statement tests for the presence of the Custom Attribute, a property of it and finally that property's value have been conducted.  This is considerably shorter than both the original and second examples which required the reflection code to obtain the Custom Attribute followed by 3 separate assertions.

This does not meet the original testing requirements which were:

  • A Custom Attribute of the correct type existed on the test method.
  • That the property to be tested of the Custom Attribute had the expected name.
  • That the property to be tested of the Custom Attribute had the correct type.
  • That the value of property to be tested of the Custom Attribute could be set.
  • That the value of property to be tested of the Custom Attribute could be obtained.
  • That the property to be tested of the Custom Attribute had the expected value.

Remaining are setting, getting (obtain) and type checking.

It turns out that that the tests for being able to set and get the property are not needed as if a property is created on a Custom Attribute then a getter and setter must be supplied.  The property can be private but if this is the case then it cannot be set as part of the Attribute syntax.  If the former condition is not met or an attempt is made to set a private property then a compilation error will occur.

Whilst successfully testing the property's value would suggest a type match this it not strictly the case as if the expected value can be converted to the type of the property then the test will be successful, e.g.

Assert.That(MethodBase.GetCurrentMethod(), Has.Attribute<FunkyAttribute>().Property("SettingOne").EqualTo(77.0));

which causes the double to be converted to an int.  It wouldn't be possible to actually set 'SettingOne' to a double value when using the attribute as this will fail to compile, e.g.

[Funky(SettingOne = 77.9)]

As this is testing an implementation of a Custom Attribute rather than its application then it is necessary to check that the implementation hasn't been accidentally changed to allow this in which case the previous erroneous test would pass.  This means testing the type.

Unfortunately this is where the Fluent interface of NUnit's Constraint model falls downs a little as it's not possible to perform multiple tests on the same initial subject which in this case is the MethodBase returned from the static MethodBase.GetCurrentMethod() call.  Therefore an additional assertion is required:

Assert.That(MethodBase.GetCurrentMethod(), Has.Attribute<FunkyAttribute>().Property("SettingOne").TypeOf<int>());

This means the original example can be reduced to the following:

[Test]
//[Funky(FunkyName = "RipSnorter")]
public void TestThatNameIsRipSnorter()
{
 Assert.That(MethodBase.GetCurrentMethod(), Has.Attribute<FunkyAttribute>().Property("FunkyName").EqualTo("RipSnorter"));
 Assert.That(MethodBase.GetCurrentMethod(), Has.Attribute<FunkyAttribute>().Property("FunkyName").TypeOf<string>());
}

[Test]
[Funky(SettingOne = 77)]
public void TestThatSettingOneIs77()
{
 // Two asserts
 Assert.That(MethodBase.GetCurrentMethod(), 
             Has.Attribute<FunkyAttribute>().Property("SettingOne").EqualTo(77));
 Assert.That(MethodBase.GetCurrentMethod(), 
             Has.Attribute<FunkyAttribute>().Property("SettingOne").TypeOf<int>());

 // Use of '.And'.  Note the trailing '.'
 Assert.That(MethodBase.GetCurrentMethod(), 
             Has.Attribute<FunkyAttribute>().Property("SettingOne").TypeOf<int>().
             And.Attribute<FunkyAttribute>().Property("SettingOne").EqualTo(77));
// Use of overloaded '&'
 Assert.That(MethodBase.GetCurrentMethod(), 
             Has.Attribute<FunkyAttribute>().Property("SettingOne").TypeOf<int>()
           & Has.Attribute<FunkyAttribute>().Property("SettingOne").EqualTo(77));
}

with the Custom Attribute definition remaining as

public class FunkyAttribute : Attribute
{
 public int SettingOne { get; set; }
 public string FunkyName { get; set; }
}
In the TestSettingOneIs77 method the need for two separate assertions has been slightly improved upon.  This is by using the 'And' method which is of the Fluent style.  The final assertion is exactly the same as the previous but just demonstrates the overloaded '&' syntax instead.  

I don't think either of these styles is particularly better than the two line equivalent as they both require two calls to obtain the Custom Attribute; one for each test.  However, using NUnit's Constraint model coupled with Fluent interface reduces the required code dramatically so is worthwhile.  Additionally I'm not sure if the Classic model actually allows Attributes to be obtained.  

A test per-property on a Custom Attribute is probably also desirable but there's nothing stopping you combining all the individual property tests into a single assertion by the use of  '.And.HasAttribute().Property().EqualTo()'.  One of these would be required  for each of the remaining properties along with a similar one for the type check.  A test per-property is more readable.


I think I'm done for a while on this subject now!

Unit Testing C# Custom Attributes with NUnit Part 2

I thought that my last post about Unit Test C# Custom Attributes with NUnit was going to be the only one.  However, after reading more of the NUnit documentation I found that despite the QuickStart guide using the Classic model the preferred model for working with NUnit is that of Constraints.  As such I thought I ought to change over to this which is what the updated code below shows.

[Test]
[Funky(FunkyName = "RipSnorter")]
public void TestThatNameIsRipSnorter()
{
 TestAttrProperty<FunkyAttribute, string>(MethodBase.GetCurrentMethod(), "FunkyName", "RipSnorter");
}

[Test]
[Funky(SettingOne = 77)]
public void TestThatSettingOneIs77()
{
 TestAttrProperty<FunkyAttribute, int>(MethodBase.GetCurrentMethod(), "SettingOne", 77);
}

// Helpers
private void TestAttrProperty<TAttr, TProp>(MethodBase method, string argName, TProp expectedValue)
{
 object[] customAttributes = method.GetCustomAttributes(typeof(TAttr), false);

 Assert.AreEqual(1, customAttributes.Count());

 TAttr attr = (TAttr)customAttributes[0];

 PropertyInfo propertyInfo = attr.GetType().GetProperty(argName);

 Assert.That(propertyInfo, Is.Not.Null);
 Assert.That(propertyInfo.PropertyType, Is.EqualTo(typeof(TProp)));
 Assert.That(propertyInfo.CanRead, Is.True);
 Assert.That(propertyInfo.CanWrite, Is.True);
 Assert.That(propertyInfo.GetValue(attr, null), Is.EqualTo(expectedValue));
}

The major change is rather that than calling Assert.<Assertion> the Constraint model starts with specifying the object to be tested followed by the test.  Additionally, the Constraint model encourages a Fluent style interface, e.g.

Assert.IsNotNull(propertyInfo);

becomes

Assert.That(propertyInfo, Is.Not.Null);

I'm not going to explain the new model here (the above link has the details) but rather this is to just point out this style which can be contrasted to the sample in the previous post.

In addition I remembered that a far easier way to obtain the current method metadata, i.e. MethodBase was to simply to use reflection by calling MethodBase.GetCurrentMethod() from System.Reflection.

You might also have noticed that in this updated example the FunkyAttribute property Name has become FunkyName.

public class FunkyAttribute : Attribute
{
 public int SettingOne { get; set; }
 public string FunkyName { get; set; }
}

This was to differentiate from the Name property of the PropertyInfo class.

However, this isn't the main reason for part 2.  However, this post seems long enough already so the good bit will come in part 3 which I'll write immediately so not too much waiting around.  A part 4 also emerged!

Wednesday, 20 July 2011

Unit Testing C# Custom Attributes with NUnit

I've been experimenting with TDD and as usual I've seemed to pick a non-standard problem to start with.  In this case I was creating a new C# Custom Attribute class, e.g.

public class FunkyAttribute : Attribute
{
 public int SettingOne { get; set; }
 public string Name { get; set; }
}

which would be used such as

[Funky(Name="SomeThingFunkierThanJust_f")]
public static int f() { return 7; }

Testing this is a little strange as rather than having a standard test method which invokes a method and asserts the result, e.g.

Monday, 18 July 2011

A Simple WPF ComobBox based Brush Selector Control

Following the last Code Project article I popped my stack and finished the original article that spawned it.  It's up on Code Project now and you can find it here or in long hand: from http://www.codeproject.com/KB/WPF/BrushSelectorArticle.aspx

As the title suggests this one shows how to implement a simple control that allows a SolidColorBrush to be selected from a panel.  In fact it demonstrates how to do with using a Style and a UserControl and compares both approaches.

Tuesday, 12 July 2011

Exploring the use of Dependency Properties in WPF User Controls

I recently wrote my first WPF User Control. This was mainly to customize a ComboBox as opposed to implement a completely new control. As such, I needed to access some of the Dependency Properties (DPs) on the ComboBox. Whilst it's possible to dip into the Content property of a UserControl this is somewhat unpleasant as it violates encapsulation. The result was that I spent a bit of time experimenting with different ways to access these DPs whilst retaining the encapsulation of the embedded ComboBox. This is all written up as a Code Project article.

http://www.codeproject.com/KB/WPF/DPsInUserControl.aspx

Sunday, 12 June 2011

Getting WPF SizeChanged Events at start-up when using MVVM and DataContext

Like lots of people working with WPF I've been writing my own MVVM framework.  I started using this in an application I was writing.  One of the things it needed to do was obtain the dimensions of a Canvas object.  As such a subscription to the SizeChanged event was used.  The connection was formed using DataBinding to my implementation of an event-to-command mapper.

The code below are the classes from the MVVM framework plus a sample application that demonstrates the problem.  This is just a button within a Canvas that when pressed pops up a dialog displaying the Canvas's dimensions.

<Window x:Class="SizeChangedEventTest2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
  xmlns:mvvm="clr-namespace:PABLib.MVVM;assembly=PABLib.MVVM"
  xmlns:local="clr-namespace:SizeChangedEventTest2">
 <Canvas mvvm:EventCommand.Name="SizeChanged" 
   mvvm:EventCommand.Command="{Binding SizeChanged}">
  <Button Content="Hello" Command="{Binding PressMe}"/>
 </Canvas>
</Window>

The code below shows my basic implementation of the command-to-event pattern.  I would have left it out but seeing but how it's used is crucial to the explanation of the problem and the solution. Please note that EventCommand is actually in the PABLib.MVVM namespace as referred to in the XAML above but I've left it out of the C# to save space.

public class EventCommand
{
 public static DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command",
    typeof(ICommand),
    typeof(EventCommand));

 public static void SetCommand(DependencyObject target, ICommand value)
 {
  target.SetValue(EventCommand.CommandProperty, value);
 }

 public static ICommand GetCommand(DependencyObject target)
 {
  return (ICommand)target.GetValue(CommandProperty);
 }

 public static DependencyProperty EventNameProperty = DependencyProperty.RegisterAttached("Name",
    typeof(string),
    typeof(EventCommand),
    new FrameworkPropertyMetadata(NameChanged));

 public static void SetName(DependencyObject target, string value)
 {
  target.SetValue(EventCommand.EventNameProperty, value);
 }

 public static string GetName(DependencyObject target)
 {
  return (string)target.GetValue(EventNameProperty);
 }

 private static void NameChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
 {
  UIElement element = target as UIElement;

  if (element != null)
  {
   // If we're putting in a new command and there wasn't one already hook the event
   if ((e.NewValue != null) && (e.OldValue == null))
   {
    EventInfo eventInfo = element.GetType().GetEvent((string)e.NewValue);

    Delegate d = Delegate.CreateDelegate(eventInfo.EventHandlerType, typeof(EventCommand).GetMethod("Handler", BindingFlags.NonPublic | BindingFlags.Static));

    eventInfo.AddEventHandler(element, d);
   }
   // If we're clearing the command and it wasn't already null unhook the event
   else if ((e.NewValue == null) && (e.OldValue != null))
   {
    EventInfo eventInfo = element.GetType().GetEvent((string)e.OldValue);

    Delegate d = Delegate.CreateDelegate(eventInfo.EventHandlerType, typeof(EventCommand).GetMethod("Handler"));

    eventInfo.RemoveEventHandler(element, d);
   }
  }
 }

 static void Handler(object sender, EventArgs e)
 {
  UIElement element = (UIElement)sender;
  ICommand command = (ICommand)element.GetValue(EventCommand.CommandProperty);

  var src = Tuple.Create(sender, e);

  if (command != null && command.CanExecute(src) == true)
   command.Execute(src);
 }
}

The bindings used in the XAML refer to properties in Window's ViewModel. This is defined as follows:

class MainWindowViewModel
{
 public ICommand PressMe { get; private set; }
 public ICommand SizeChanged { get; private set; }

 private int m_width = 0;
 private int m_height = 0;

 public MainWindowViewModel()
 {
  SizeChanged = new PABLib.MVVM.RelayCommand<object>((x) =>
  {
   SizeChangedEventArgs args = (SizeChangedEventArgs)((Tuple<object, EventArgs>)x).Item2;
   m_width = (int)args.NewSize.Width;
   m_height = (int)args.NewSize.Height;
  });

  PressMe = new PABLib.MVVM.RelayCommand<object>((x) =>
  {
   MessageBox.Show(string.Format("Width:{0}, Height:{1}", m_width, m_height));
  });
 }
}

For the sake of completeness here is the implementation of RelayCommand. This is pretty much the basic version as originally created by Josh Smith.

public class RelayCommand<T> : ICommand
{
 Action<T> _Execute { get; set; }
 Predicate<T> _CanExecute { get; set; }

 public RelayCommand(Action<T> execute, Predicate<T> canExecute = null)
 {
  _Execute = execute;
  _CanExecute = canExecute;
 }

 public bool CanExecute(object parameter)
 {
  if (_CanExecute == null)
   return true;
  else
   return _CanExecute((T)parameter);
 }

 public void Execute(object parameter)
 {
  if (_Execute != null)
   _Execute((T)parameter);
 }

 public event EventHandler CanExecuteChanged
 {
  add { CommandManager.RequerySuggested += value; }
  remove { CommandManager.RequerySuggested -= value; }
 }
}

However, rather than just obtaining the dimensions when changed these were also required when the Canvas was first shown.  The problem was that when using my MVVM framework it was only capturing events if the window was resized but not the initial sizing event.  For the sample app. this meant pressing the button the first time yielded results of 0 for both width and height.  I switched back to a conventional code-behind page approach as a sanity check. This worked!

At this point I started debugging the code more and discovered that the initial SizeChanged event was being fired and handled by the EventCommand code.  However, when it came to invoke the ICommand associated with the EventCommand this was null (in the Handler method of EventCommand).  The strange thing here was that that the event name had been successfully passed to EventCommand but the command hadn't.  Both of these are stored as Attached Properties (as is normal for event-to-command implementations).

The difference between the event name and the command is that event name was a hard-coded string in the XAML whereas the command was being obtained using data binding to the main window's ViewModel.  Therefore the culprit appeared to be that the binding hadn't executed.  There was no problem with the validity of the binding as all the SizeChanged events bar the initial were being received and in debug mode VS was not reporting an issues with the binding.

The only thing I could think of is that the initial event was being fired before the binding had been processed.  This was confirmed by extending the Attached Property definition for the CommandProperty to include an CommandChanged callback e,.g.

public static DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command",
   typeof(ICommand),
   typeof(EventCommand),
   new FrameworkPropertyMetadata(CommandChanged));

private static void CommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
}

A break point set on CommandChanged showed this wasn't invoked until after the event had fired confirming that the binding hadn't occurred.

The way the ViewModel was set as the Data Context for the main Window was by removing the StartupUri element from the Application element in App.xaml.cs, e.g.

<Application x:Class="SizeChangedEventTest2.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

and modifying App.xaml.cs to be:

public partial class App : Application
{
 protected override void OnStartup(StartupEventArgs e)
 {
  base.OnStartup(e);

  MainWindowViewModel vm = new MainWindowViewModel();
  MainWindow win = new MainWindow();
  win.DataContext = vm;

  this.MainWindow = win;
  this.MainWindow.Show();
 }
}

After some searching I noticed other projects setting the DataContext of the main window (to the ViewModel) in different ways.  This got me to thinking that perhaps the DataContext was being established too late.

To address this App.xaml and App.xaml.cs were put back to their initial states and instead the ViewModel created and attached in the constructor for MainWindow, e.g.

public partial class MainWindow : Window
{
 public MainWindow()
 {
  this.DataContext = new MainWindowViewModel();

  InitializeComponent();
 }
}

This fixed the problem!  As an experiment InitializeComponent() was moved to top of the constructor.  It stopped working. I didn't particularly like creating the ViewModel here so instead this code was removed and instead it was created in XAML as follows:

<Window x:Class="SizeChangedEventTest2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
  xmlns:mvvm="clr-namespace:PABLib.MVVM;assembly=PABLib.MVVM"
  xmlns:local="clr-namespace:SizeChangedEventTest2">
 <Window.DataContext>
  <local:MainWindowViewModel/>
 </Window.DataContext>
 <Canvas mvvm:EventCommand.Name="SizeChanged" mvvm:EventCommand.Command="{Binding SizeChanged}">
  <Button Content="Hello" Command="{Binding PressMe}"/>
 </Canvas>
</Window>

This too worked.   This is where I'm currently at.  From this I conclude that it is critically important to make sure that a View's DataContext is properly created and attached before the underlying Window is displayed otherwise initial events will be missed.

Monday, 23 May 2011

First ever CodeProject article

I've been playing around with the WPF TreeView control trying to get it to draw a connected line org. chart style view of a tree.  I was going to write it up here but it got a bit long and formatting for the blog is a little tricky so I turned it into a Code Project article, my first one.  You can find it here.

Wednesday, 28 February 2007

Evolution of C# enumerators

Introduction

I needed a very simple tree data structure the other day. Unfortunately C#/.NET doesn’t provide one so I implemented a simple one. The need was to create a hierarchy of folders from a flat data structure where each node contained a unique id and its parent id. The list wasn’t particularly ordered, i.e. not by depth or breadth however parent nodes always preceded child nodes so that when a node was added to the tree the parent was guaranteed to already be there. This wasn’t the important part of the exercise. The main thing I wanted to accomplish was to perform a depth first search displaying the node’s contents indented to reflect the depth that it occurred in the tree.

As this was written in C# and .NET collections are expected to support the IEnumerable interface I didn’t just want to implement a basic tree walker but do it in such a way that it conforms to the .NET paradigm. As it’s a while since I’ve implemented a tree and this is the first time I’ve used C# 2.0 enumerators I ended up going through 3 iterations of enumerator until I had what I thought was proper .NET style enumerator. This article describes this evolution. Please note that thread safety is not considered and little attention is paid to error handling or invalid conditions.

The following code shows the minimal implementation of the tree bar any enumeration code.

class Node
{
  public static Node MakeRoot() 
  {
    return new Node(0); 
  }
  private Node(int id) { id_ = id; }
  public bool Add(int id, int parentId)
  {
    if (parentId == id_)
    {
      children_.Add(new Node(id));
      return true;
    }
    else
    {
      foreach (Node child in children_)
        if (child.Add(id, parentId) == true)
          return true;
      return false;
    }
  }

  public int Id { get { return id_; } }
  private int id_ = -1;
  ArrayList children_ = new ArrayList();
}
The main program just loads a simple tree.

Node root = Node.MakeRoot();

root.Add(1, 0);
root.Add(2, 0);
root.Add(3, 0);
root.Add(11, 1);
root.Add(12, 1);
root.Add(13, 1);
root.Add(121, 12);
root.Add(122, 12);
root.Add(1211, 121);
root.Add(12111, 1211);

C Approach

Performing a depth first search is not difficult. The easiest way to implement this is to use recursion. The following is a quick implementation that proved the tree was functioning correctly.

Note that this is a member of the Node class.

public void Walk(int level)
{
  for (int i = 0; i < level; ++i)
    Console.Write("\t");

  Console.WriteLine(id_);

  foreach (Node node in children_)
    node.Walk(level + 1);
}
This implementation is how a tree would have been walked in the era of C programming. In the OO and .NET world it has a number of problems:
  1. Breaks encapsulation as the application code, i.e. the display code is mixed with that of the data structure. Using straight C this code could be fixed by having the method take a function pointer as an argument which would be invoked for each node to display the node. In C++ this could be improved by using a functor or by implementing the whole thing as an STL compatible iterator.
  2. The method runs until completion, i.e. it is not possible to obtain an item from the tree and perform some action on it then retrieve the next or abandon the walk altogether. However, the method could be extended to provide a mechanism to terminate early depending on the return value of the invoked method.
  3. .NET 2.0 collections are expected to implement the IEnumerable interface which means they must provide a IEnumertor GetEnumerator().  This allows the collection to be used by any .NET entity that recognizes the standard enumeration interfaces in particular the foreach keyword which is recognized as the best mechanism for enumerating a collection.

C# 1.0 Approach

These issues can be addressed by implementing the tree walker as an enumerator. The main difficulty in doing this is that an enumerator is an iterative operation which means a separate call is made to advance the iterations whereas the tree walker is called once and only returns when the traversal is complete.

An enumerator for data structures that are suited to recursive traversal can be implemented using various techniques. Firstly on the initial call the enumerator could walk the tree recursively and build up a linear data structure that is ideally suited to iteration, i.e. create a list of depth first traversal whose members reference the actual nodes of the tree then iterate over members of the list.

The method I choose was to mimic recursion by maintaining context in the enumerator that upon the following call would take the enumerator back to where it left off. The enumerator is implemented in a separate class which can hold the state and as per the iterator pattern allow multiple instances to co-exist. The following code shows the implementation but note that even though not explicitly shown this is a nested class so has access to Node’s private members and is not visible to the caller which works only against the IEnumerator interface. It is this interface that requires the implementation of MoveNext(), Current & Reset().

class WalkNode : IEnumerator
{
  public WalkNode(Node root)
  {
    root_ = root;
  }
  bool IEnumerator.MoveNext()
  {
    if (current_ == null)
    {
      current_ = root_;            
      activeIts_.Push(root_.children_.GetEnumerator());
      return true;
    }
    else
    {
      while (activeIts_.Count > 0)
      {
        IEnumerator it = (IEnumerator)activeIts_.Pop();
        if (it.MoveNext() == true)
        {
          current_ = (Node)it.Current;
          activeIts_.Push(it);
          activeIts_.Push(current_.children_.GetEnumerator());
          return true;
        }
      }

      return false;
    }
  }
  object IEnumerator.Current
  {
    get 
    { 
      // Need to handle invalid current_
      return new NodeAndLevel(current_, activeIts_.Count - 1); 
    }
  }
  void IEnumerator.Reset() { current_ = null; activeIts_.Clear(); }
  Node root_;
  Node current_;
  Stack activeIts_ = new Stack();
}
The interesting stuff happens in MoveNext(). This is called to advance the enumerator and must be called to set the enumerator to the first item before actually using its value, i.e. calling the Current property.

On the first call the current node is set to the root node. This means that if the Current property is called then the root node will be returned. Secondly it sets the enumerator up for the subsequent call by obtaining an enumerator to the root node’s children and pushing it onto a stack stored in the enumerator. It is this stack that effectively mimics the recursion as it persists the enumerator for the current node and those in the branch above across each call and so maintains a reference to the next node to visit and which one to return to when there are no more children.

On the next (non-root node) and all subsequent calls a test is made to see if the stack contains any items. If it doesn’t then this means there are no more nodes to visit and the tree has been fully traversed. When called the second time the stack will contain the enumerator for the root node’s children. Due to the nature of the Node class a node will always be able to provide a enumerator even if doesn’t have any children but the first call to MoveNext() on it will return false indicating the end of the children, i.e. none. If the root has no children then this will be case as the enumerator (for its children) obtained from the stack will return false, the stack count will be zero so the loop will terminate and the main MoveNext() will return false indicating an end of the traversal. This will also be case when all the children of the root have been traversed.

The other case is that the root does have children in which case the internal call to MoveNext(), i.e. using the enumerator from the stack will return true in which case the member variable current_ used to implement the Current property will be set to the child node obtained from the Current property of the internal enumerator. As this is a depth first search the next node to be traversed should be the first child of this node so the current enumerator is pushed onto the stack along with the newly obtained internal enumerator for the current node’s children so on the next call its children will be enumerated. True is then returned.

In the case of the bottom of a branch being reached the internal call to MoveNext() from the just popped enumerator will return false. As the stack still has the parent enumerators on it the loop will not terminate unlike the case of a root node without children or having traversed its last. This then causes the current node’s parent’s enumerator to become the current enumerator allowing the next child along to be traversed if there is one. This continues until the stack has been popped so that current internal enumerator is that of the root node. If this contains more children the each of these nodes is traversed deeply until no more children are found causing the loop to terminate as the stack is empty and finally returning false indicating the end of the traversal.

The downside of the mimicking approach is the number of live internal enumerators that are kept alive on the stack whilst traversing deeper children. If the deepest point of the tree was 100 nodes deep then this would require 100 active internal enumerators to be on the stack. The deepest enumerator, i.e. number 100 would be for the leaf node and will yield no children.

Rather than returning the reference to a node an instance of a wrapper type is returned which allows the additional level information to be supplied. The definition of this is shown below.

class NodeAndLevel
{
  public NodeAndLevel(Node node, int level)
  {
    node_ = node;
    level_ = level;
  }

  public Node Contents { get { return node_; } }
  public int Level { get { return level_; } }

  readonly Node node_;
  readonly int level_;
} 
The other modification is that Node implements the IEnumerable interface which means it must implement the GetEnumerator() method which it does. This creates an instance of the WalkNode enumerator that we have just discussed as can be seen below.

IEnumerator IEnumerable.GetEnumerator()
{
  return new WalkNode(this);
}

C# 2.0 Approach

Version 2.0 of C# added language support to make the implementation of enumerators simpler. This allows the implementation of this particular enumerator to be reduced and simplified dramatically.

class Node : IEnumerable
{
  IEnumerator IEnumerable.GetEnumerator()
  {
    return GetEnumeratorWithLevel(0);
  }
  private IEnumerator GetEnumeratorWithLevel(int level)
  {
    yield return new NodeAndLevel(this, level);
    foreach (Node node in children_)
    {
      using (IEnumerator it = node.GetEnumeratorWithLevel(level + 1))
      {
        while (it.MoveNext())
          yield return it.Current;
      }
    }
  }
  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  {
    return this.GetEnumeratorWithLevel(0);
  }

… the rest is the same as Node at the beginning

The entire enumerator code has now been reduced to the implementation of GetEnumerator(), well almost. The helper GetEnumeratorWithLevel() is also required so an additional argument can be passed. As GetEnumerator() is implementing the interface IEnumerable<> as inherited by Node its signature cannot vary hence why it calls the helper method. As IEnumerable<> derives from the C# 1.0 interface IEnumerable as used in the previous example the weakly typed IEnumerable.GetEnumerator() must also be implemented but as can be seen this is done by calling the strongly typed version.

As generics is available the tree code has switched to using generics. This is a good thing as the caller of the enumerator is dealing with strongly typed objects that don’t require a runtime cast any more.

The enumerator class hasn’t really gone away rather the compiler has implemented it for us as a nested class just as we had to do by hand in the previous version. Again, just like the C# 1.0 implementation which used a stack to maintain the recursive state the generated code also maintains state. The key to allowing the compiler to do this is the yield return statements. This informs the compiler where the enumerator should return and that the subsequent call to MoveNext() should begin immediately after it.

In this example, the enumerator is initially called with the root node. This then yields (returns) immediately, creating a new instance of NodeLevel which will be accessible via the generated Current property.

The next call causes the enumerator to create an internal enumerator (as before in the C# 1.0 implementation) of the current node’s children, i.e. from the children_ list. This will then call MoveNext() on this internal enumerator. If the root node has no children then it will terminate and false will be returned indicating that the traversal is complete. If there are children then the yield will cause a return true and the current node will become that child. As the enumerator was created by calling GetEnumeratorWithLevel() this is effectively a recursive call but with the yield causing the return with the generated code maintaining the state including storing the references to all the internal enumerators.

Even though the generated code is hard to read and full of gotos using Reflector allows the generated code to be seen. As this implements IEnumerator<> and the derived IEnumerator Current is implemented for both and Reset for the latter. In addition, as IEnumerator<> is also derived from IDisposable Dispose is also created. This is why the apparent recursive call to GetEnumeratorWithLevel() wraps the resulting call with a using statement so that Dispose() is called.

The generated code still has to do everything the hand-coded version did including keeping open any active enumerators. As it’s generated it might be faster too but I haven’t tested this. However, it has freed us from having to write & maintain this code.

How to prevent Visual Studio 2005 designer from running your code

I created a control that inherited from System.Windows.Forms.TreeView. As it derived from the a control class Visual Studio 2005 (VS05) kindly automatically added to the Project Components section of the Toolbox (sidebar). From here I could happily drag'n'drop my control on to a form, which I did! However, my derived control upon construction performed a recursive enumeration of all the folders on my C: drive to populate the tree view. This was fine when the program was executing but it appears that in the design view VS05 also runs the constructor. This meant the recurisve and I did I say fairly time consuming enumeation occured in the design view effectively grinding all my work to a halt.

Anyway, I figured there must be a way to turn this off so; most likely using an Attribute. However, I could find nothing. Following some googling I came across some code that could be used detect from where your code was being run or to be more accurate was it being be run from within VS05.

So, just in case you have the same problem here it is:


if (this.Site == null this.Site.DesignMode == false)
; // This will only executee code when not running in VS05, i.e. normal execution