Polymorphic enums in C#, generic incrementation

During the implementation of my polymorphic enum, I have chosen to allow several types for the underlying “ordinal” value, as it is also possible for standard C# enums…

From the MSDN documentation, the allowed underlying types for enum types are the following (although other value types such as char are eligible, their use is not recommended) :

Type

Size

sbyte

Signed 8-bit integer

byte

Unsigned 8-bit integer

short

Signed 16-bit integer

ushort

Unsigned 16-bit integer

int

Signed 32-bit integer

uint

Unsigned 32-bit integer

long

Signed 64-bit integer

ulong

Unsigned 64-bit integer

In order to enable the ordinal parameter to be optional in the registration of enum values, I had to find a way to compute an automatic value. The rule I wanted to apply was very simple : if there is no value already register, use zero, else use the maximum value already registered, plus one. But how do you write such code without checking the type in an ugly fashion ?

Generic constraints are somehow limited : I can force the ordinal type to be a value type by using a “where T : struct” constraints, but there is no such thing as a “IPrimitiveNumericValue” interface !

Here is where I got to, using generics and lambdas…

public static class Incrementer
{
    private static Func<T, T> GetFunc<T>(Func<T, T> f)
    {
        return f;
    }
    [...]

I first define static class and a private static helper function that take a Func<T, T> and returns… the unmodified argument. This is just a hint for the compiler, because I’m going to use lambdas and as you might know, a lambda can either be converted to a delegate (code) or to an expression tree representing the lambda (data). Without any indication, the compiler can’t infer the expected type, so we have to help him…

Then, the class defines a static field and initialises it in its static constructor :

private static Dictionary<Type, object> incrementers;

static Incrementer()
{
    incrementers = new Dictionary<Type, object>();
    incrementers.Add(typeof(sbyte), GetFunc<sbyte>(i => (sbyte)(i + 1)));
    incrementers.Add(typeof(byte), GetFunc<byte>(i => (byte)(i + 1)));
    incrementers.Add(typeof(short), GetFunc<short>(i => (short)(i + 1)));
    incrementers.Add(typeof(ushort), GetFunc<ushort>(i => (ushort)(i + 1)));
    incrementers.Add(typeof(int), GetFunc<int>(i => i + 1));
    incrementers.Add(typeof(uint), GetFunc<uint>(i => i + 1));
    incrementers.Add(typeof(long), GetFunc<long>(i => i + 1));
    incrementers.Add(typeof(ulong), GetFunc<ulong>(i => i + 1));
}

At this point, all the required incrementing functions are expressed as lambdas and registered in a dictionary.

The only method left to write is the PlusOne method :

public static T PlusOne<T>(this T value)
    where T : struct
{
    object incrementer;
    if (!incrementers.TryGetValue(typeof(T), out incrementer))
        throw new NotSupportedException(
            "This type is not supported.");

    return ((Func<T, T>)incrementer).Invoke(value);
}

Type checking and dictionary lookup. That’s it !

Posted in Syntax Puzzles | Tagged , , | Comments Off

Polymorphic enums in C# ?

Using Java as a inspiration source for C# (hmm wait, hasn’t that already been done from the start ?)

A few weeks ago, I read this post by @cyriux, describing how you could use polymorphic enums in Java. Actually, I had already heard him telling that enums in C# were nothing like the ones in Java. And even if he’s sometimes trolling, he’s really got a point there. Then I thought to myself : I know I won’t be able to add this syntax to C#, because I can’t change the compiler, but how clause could I get to polymorphic enums ? Let’s try that…

First, what are the common characteristics of an enum ?

  • enums bind together a scalar value and a string representation, so enums can be converted to and parsed from strings
  • for the same reason, enums can be casted to and from scalar values (int, long, short…),
  • enums should be immutable (in fact, unless you introduce some mutable state in them, they already are),
  • enums cannot be extended by other types : once defined, their set of values is closed and cannot be modified.

I haven’t checked for Java, but here are some other characteristics of C# enums :

In order to build a type that behaves like an enum, I’ve made the following decisions :

  • I want to build a base type from which actual enums will derive. As there is nothing in C# as an abstract struct (value type), I have to implement a class and not a struct.
  • In order to obtain a value type behaviour (value comparison instead of instance equality), I’ll will have to implement it.
  • I will implement interfaces IComparable and IConvertible, but I haven’t really seen any use case where I would use IFormattable, so I chose not to implement it.
  • Enums in C# don’t have an Ordinal property, but I’ll introduce one, so that I can write unit tests as close as possible as @cyriux’s ones. It will look a little bit Java-ish… but of course I’ll keep the C# casing convention.
  • The underlying type used to represent an enum is an integer by default, but other types can be used, such as a long or an unsigned short. I will try to make the enums definitions as short a possible, so I’ll use generics and take advantage of the type inference system.

My C# enum has behaviour

Enough text there ! Directly inspired from @cyriux’s post’s first sample “Rock – paper – scissors”, here is the test cases that I want to execute :

[TestMethod]
public void paper_beats_rock()
{
    Assert.IsTrue(Gesture.PAPER.Beats(Gesture.ROCK));
    Assert.IsFalse(Gesture.ROCK.Beats(Gesture.PAPER));
}

[TestMethod]
public void scissors_beats_paper()
{
    Assert.IsTrue(Gesture.SCISSORS.Beats(Gesture.PAPER));
    Assert.IsFalse(Gesture.PAPER.Beats(Gesture.SCISSORS));
}

[TestMethod]
public void rock_beats_scissors()
{
    Assert.IsTrue(Gesture.ROCK.Beats(Gesture.SCISSORS));
    Assert.IsFalse(Gesture.SCISSORS.Beats(Gesture.ROCK));
}

And here is the implementation of the enum, built upon my PolymorphicEnum class :

/** PolymorphicEnum have behavior! **/
public class Gesture : PolymorphicEnum<Gesture>
{
    public static Gesture ROCK = Register<RockGesture>();
    public static Gesture PAPER = Register();
    public static Gesture SCISSORS = Register();

    // we can implement with the integer representation
    public virtual bool Beats(Gesture other)
    {
        return this.Ordinal - other.Ordinal == 1;
    }

    private class RockGesture : Gesture
    {
        public override bool Beats(Gesture other)
        {
            return other == SCISSORS;
        }
    }
}

As you can see in the implementation, it is now possible to define a Gesture enum, that exposes 3 static properties of type Gesture. One of these properties, ROCK, is in fact an instance of RockGesture, which is a Gesture that overrides the behaviour of Beats method.

Strategy Pattern

All the Java sample from the post can now be ported to C# ! The next one was the Eurovision contest, where an abstract method was defined in the base enum, and overridden in each enum instance, in order to implement a strategy pattern. This is where I admit I couldn’t get the same behaviour, as for internal implementations reasons I needed my base class to not be abstract… So I had to define a default behaviour :

public class EurovisionNotification
    : PolymorphicEnum<EurovisionNotification>
{
    /** Default behavior : I don't want to know ! */
    public virtual bool MustNotify(String eventCity,
                                   String userCity)
    {
        return false;
    }

    /** I love Eurovision, don't want to miss it, never! */
    private class EurovisionNotificationAlways
        : EurovisionNotification
    {
        public override bool MustNotify(string eventCity,
                                        string userCity)
        {
             return true;
        }
    }

    /**
     * I only want to know about Eurovision if it takes place
     * in my city, so that I can take holidays elsewhere at
     * the same time
     */
    private class EurovisionNotificationOnlyCity
        : EurovisionNotification
    {
        public override bool MustNotify(string eventCity,
                                        string userCity)
        {
             return eventCity.Equals(
                userCity,
                StringComparison.InvariantCultureIgnoreCase);
        }
    }

    public static EurovisionNotification ALWAYS =
        Register<EurovisionNotificationAlways>();
    public static EurovisionNotification ONLY_IN_MY_CITY =
        Register<EurovisionNotificationOnlyCity>();
    public static EurovisionNotification NEVER =
        Register();
}

State Pattern

The next sample is the one where a baby is represented as a state machine :

public class BabyState : PolymorphicEnum<BabyState>
{
    public static BabyState POOP = Register();

    public static BabyState SLEEP =
        Register(data: new { Next = POOP });

    public static BabyState EAT =
        Register(data: new { Next = SLEEP });

    public static BabyState CRY =
        Register(data: new { Next = EAT });

    public BabyState Next(bool discomfort)
    {
        if (discomfort)
            return CRY;

        return this.Data == null
            ? EAT
            : (BabyState)((dynamic)this.Data).Next;
    }
}

Just as for the Java enums, “we can reference enum constants between them, with the restriction that only constants defined before can be referenced”. The workaround here, as @cyriux wrote in his post, is to open the cycle. This builds allows us to build the graph on the right.

We can notice here that in order to embed data in an enum value, I have introduced an extra parameter “data” in the Enum method, which is responsible for the Enum values registration. Using this extra parameter, we can go back to the Eurovision sample and rewrite this way :

using Policy = System.Func<string, string, bool>;

public class EurovisionNotificationLambda
    : PolymorphicEnum<EurovisionNotificationLambda>
{
    private static Policy Policy(Policy f) { return f; }

    public static EurovisionNotificationLambda ALWAYS =
        Register(data: Policy((eventCity, userCity) => true));

    public static EurovisionNotificationLambda ONLY_IN_MY_CITY =
        Register(data: Policy((eventCity, userCity) =>
            eventCity.Equals(
                userCity,
                StringComparison.InvariantCultureIgnoreCase)));

    public static EurovisionNotificationLambda NEVER =
        Register(data: Policy((eventCity, userCity) => false));

    public bool MustNotify(String eventCity, String userCity)
    {
        return ((Policy)this.Data).Invoke(eventCity, userCity);
    }
}

In this implementation, each enum value owns its notification policy, in the form of a types delegate, which is declared using a lambda expression.

Enum-non-optimized collections

Ok, I haven’t gone so far as implementing optimized collections that take advantage of the integer nature of enums ! So not all the arguments listed by @cyriux apply to my C# implementation… But I still get polymorphism, the correct Equals, GetHashCode, ToString, string or integer serialization, and singleton-ness for free, with very little code ! Feel free to experiment with it if you want, the whole project will be available on my GitHub very soon.

In a next post, I’m going to talk about some points of interest in my PolymorphicEnum implementation.

Posted in Syntax Puzzles | Tagged , , , | Comments Off

Using BDD and SpecFlow to write readable tests

In this post, I’m going to use SpecFlow and the Gherkin syntax to write tests in a natural language. I want to show how easy that is to setup, when you have code that is already testable, and how it helps you to write better tests in a few minutes.

SpecFlow is a testing component / framework / Visual Studio plug-in, which allows you to write your tests in a natural fashion, and run these tests using your favourite test-runner. As quoted from their web site :

SpecFlow aims at bridging the communication gap between domain experts and developers by binding business readable behavior specifications to the underlying implementation. Our mission is to provide a pragmatic and frictionless approach to Acceptance Test Driven Development and Behavior Driven Development for .NET projects today.

SpecFlow is build upon the Gherkin syntax, which is a grammar that has been designed to write behaviour specifications. This syntax first emerged in the Ruby community, and is linked to a project called Cucumber. For more details, you can check out http://cukes.info :

Cucumber is Aslak Hellesøy’s rewrite of RSpec’s “Story runner”, which was originally written by Dan North. (Which again was a rewrite of his first implementation – RBehave. RBehave was his Ruby port of JBehave)…

Gherkin is Cucumber’s DSL (Domain Specific Language) and as such, is not linked to a particular language or technology. It can therefore be used in .NET by using SpecFlow. It has very few keywords, yet is very powerful. The best way to explain how it works is to show an example of a test scenario :

Scenario: Filter on age
    Given I have written a query against the provider
    And I have added a Age >= 36 where clause
    Given The people finder service filters on Age >= 36
    When I execute the query
    Then The service parameter should be Age IsGreaterThan 36
    And The result count should be 3
    And The result should validate the servicePredicate

From now on, you might have noticed that I’m working on my Linq provider again… but in this post I’ll talk only about testing and using SpecFlow, so don’t run away, even if you’re sick of expression trees !

What SpecFlow allows you to do, is to write your specifications and tests cases in plain text, and generate tests classes from it. It has several nice features that help you organize your tests and examples, which I’ll describe soon.

In order to use SpecFlow in your project, the easiest way is to add a reference to it in your test project, using the NuGet package manager. To get Visual Studio integration, you should also install the “SpecFlow integration for Visual Studio extension”.

When doing BDD, the tests are written in order to tests features. For each feature of an application (or component, or class), you can create a feature file. As you can see from the previous example, tests will be organised around the concept of “scenario”. Each feature file can contain several scenarios. The binding between a scenario and the actual tests implementation will be done on a line-by-line basis. Each line of the scenario will end up as a method call :

  • the “Given” and associated “And” clauses will correspond to methods that set up the tests,
  • the “When” clause will trigger some action or event that drives the behaviour that is aimed to be tested,
  • the “Then” and associated “And” clauses will perform the assertions that determine the outcome of the test.

In order to do the matching between lines in the scenario and methods in the test class, the methods are marked with the appropriate SpecFlow attributes, that take the model of the expected sentence as an argument. This model can include groups of capturing expressions, that are used to populate the method parameters at run time.

[Given(@"I have added a (.*) where clause")]
public void GivenIHaveAddedAWhereClause(string predicate)

If we go back to the test scenario shown earlier, the best way to see how the test is executed is to look at the generated test output:

Given I have written a query against the provider
-> done: FeaturesTest.GivenIHaveWrittenAQuery() (0,0s)
And I have added a Age >= 36 where clause
-> done: FeaturesTest.GivenIHaveAddedAWhereClause("Age >= 36") (0,0s)
Given The people finder service filters on Age >= 36
-> done: FeaturesTest.GivenThePeopleFinderServiceFiltersOn("Age >= 36") (0,0s)
When I execute the query
-> done: FeaturesTest.WhenIExecuteTheQuery() (0,1s)
Then The service parameter should be Age IsGreaterThan 36
-> done: FeaturesTest.ThenTheServiceParameter("Age IsGreaterThan 36") (0,0s)
And The result count should be 3
-> done: FeaturesTest.ThenTheResultCount(3) (0,0s)
And The result should validate the servicePredicate
-> done: FeaturesTest.ThenTheResultShouldValidatetheServicePredicate() (0,0s)

We can see that each line of the scenario is used to call a method. In order to “accumulate” the conditions and perform the assertions on the results, we use a class that defines the test context :

public class ServiceContext
{
    // Data context
    public IEnumerable<Person> AllPeople { get; set; }

    // Input
    public List<string> Query { get; set; }
    public List<string> ServiceLambdas { get; set; }

    // Service predicate, built upon the ServiceLambdas
    public Expression<Func<Person, bool>>
                            ServicePredicate {get; set;}

    // Output
    public List<Person> Results { get; set; }
    public SearchCriteria PassedCriteria { get; set; }
}

Using this context class, the methods corresponding to the “Given” populate the properties used as the test input, the “When” performs the action, which populates the output based on the input, and the “Then” make assertions on the output.

The next step is to add additional test cases. A simple way could be to simply copy-paste the previous scenario, and change the parameters. But as we always want to void duplication, we’ll use a very handful feature here and use a “Scenario Outline” and examples :

Scenario Outline: Filter on a single criterion
    Given I have written a query against the provider
    And I have added a <predicate> where clause
    Given The people finder service filters on <servicePredicate>
    When I execute the query
    Then The service parameter should be <serviceParameter>
    And The result count should be <resultsCount>
    And The result should validate the servicePredicate
    Examples: 
    | predicate                     | servicePredicate              | serviceParameter            | resultsCount |
    | Age >= 36                     | Age >= 36                     | Age IsGreaterThan 36        | 3            |
    | Age >= 36                     |                               | Age IsGreaterThan 36        | 6            |
    | FirstName.StartsWith("Scar")  | FirstName.StartsWith("Scar")  | FirstName StartsWith Scar   | 1            |
    | LastName == Alba              |                               | LastName Equals Alba        | 6            |

The main advantage of this syntax is that it is self-explanatory ! Once the scenario outline is prepared, we list all the cases that we want to test.

If you’ve read the post carefully up to this point, you might have noticed that my scenario makes assertions on the number of results, but that there is nothing that sets-up the test data. In fact, there is a hidden “Given” clause that is used across the whole feature file. The way to to this is by using the keyword “Background”:

Background: 
    Given The people are
    | FirstName | LastName    | Age | Id                                     |
    | Scarlett  | Johansson   | 27  | {8c319634-935d-4681-adcc-02d5347fe6c4} |
    | Jessica   | Alba        | 31  | {32a84597-8c3d-44bc-a1a5-6538188e9d25} |
    | Penelope  | Cruz        | 38  | {5aa0eb59-3961-472f-b829-7d54ac8eeeef} |
    | Reese     | Witherspoon | 36  | {77fcd741-3839-4692-925f-a3a0eb19cf42} |
    | Charlize  | Theron      | 36  | {e37290f6-d376-44e2-944d-d0af13c1a75c} |
    | Mouloud   | Achour      | 31  | {18af541a-a5dc-41d2-af47-479b1c06e216} |

One last thing : although parsing the lambda given as arguments in the scenario is a topic of its own and could be discussed further, setting up the test data from the previous “Given” clause is delightfully easy, and I couldn’t help not showing you the code :

[Given(@"The people are")]
public void GivenThePeopleAre(Table people)
{
    this.context.AllPeople = people.CreateSet<Person>();
}

As a conclusion, I strongly recommend to give SpecFlow a try, you won’t regret it !

All the source code from this post and the Linq Provider Series is now available on my Github at https://github.com/pirrmann/LinqToService. Please feel free to fork and/or contribute, and I’d also be really happy to get feedback !

Posted in LINQ | Tagged , , , , , | Comments Off

Linq provider : an attempt… part 6

Jammin’ Jammin’

Just a month ago, I’ve had the opportunity to get feedback from @cyriux and Jérôme during the monthly @ArollaFr’s Code Jam, and we made important changes in the code.

The concept of a Code Jam is simple : we meet once a month to practice our coding skills, emphasizing practices such as TDD and pair-programming.
For more details (in French) : http://www.arolla.fr/evenements-2/jams-de-code/

June’s theme was “Testing things that are difficult to test”. The session started with a “Lightning talk” by @cyriux, describing several situations where testing can be quite complicated, as for instance :

  • When time is involved
  • When parallelization and multi-threading is involved
  • When architecture is involved (network bandwidth, fault-tolerant systems)
  • Testing security (SQL injection, various kinds of exploits)
  • When the host is difficult to emulate (as example: how to test an eclipse plug-in ?)
  • Testing with non-trivial outputs/inputs: images, sounds, documents, reports, big messages…
  • Testing with large configuration problems: realistic search index, social algorithms, time series for financial analytics…

After this introduction, we were looking for a practical example of such a situation, and I suggested we could take a look at my implementation of this Linq provider. I haven’t gone very far yet, but my goal with this Linq to web service provider is to make the service return filtered data based on the Linq query. This means that I want the filtering to happen inside the web service, and not on the client side. And this is of course a behaviour that I want to test:

After some discussion, @cyriux pointed to me that there were several false assumptions in the way I was testing things. I assumed I would be testing the provider by using it against a service that I had built myself… but I had no need for an actual web service implementation ! The service and the provider are two separate features, and mustn’t be unit-tested at the same time.

I have not completely given up the idea of implementing the service, but it is now a separate objective that has nothing to do with the provider implementation. And the fact that the service is a web service is just an implementation detail. My vision of the way to organize the project is now the following :

The solution is now only composed of 3 assemblies :

  • PeopleFinder, which defines the service interface (i.e. the contract) and POCOs used as simple Data Transfer Objects,
  • LinqToService, which contains the actual implementation of the Linq provider,
  • UnitTests, which contains the tests and a “lambda-based” implementation of the PeopleFinder interface.

This organisation allows us to test only the behaviour of the provider, providing our own implementation of the service. To do so, we introduced a PeopleFinderLocator class. This might change in the future, but is quite out of scope here…

Given a query expression, the Linq provider’s goal is just to give the service the good parameters, and perform additional work that the service cannot handle. Here, the service knows how to filter the people based on their age. Let’s consider the following query :

var query = new QueryableServiceData<Person>()
    .Where(p => p.Age >= 36);

When executing it, the provider must call the service with the appropriate parameter, and mustn’t do any additional work except handling the result back to the caller. The situation should be the following :

And here is a test corresponding to this situation :

[TestMethod]
public void GivenAProviderWhenIFilterOnAgeGT36ThenItFilters()
{
    LambdaBasedPeopleFinder peopleFinder =
        new LambdaBasedPeopleFinder(p => p.Age >= 36);
    PeopleFinderLocator.Instance = peopleFinder;

    QueryableServiceData<Person> people =
        new QueryableServiceData<Person>();

    var query = people
        .Where(p => p.Age >= 36);

    var results = query.ToList();

    Assert.IsTrue(results.All(p => p.Age >= 36));
    Assert.AreEqual(
        new IntCriterion()
            {
                FilterType = NumericFilterType.IsGreaterThan,
                Value = 36
            },
            peopleFinder.PassedCriteria.Age);
}

In the previous test, we use a LambdaBasedPeopleFinder implementation of the service, that actually filters some sample data based on a predicate. In some way we rely on this implementation because we test that the results are correctly filtered. But we can even test that the provider doesn’t do the service’s work !

If we adapt the previous test by replacing the lambda by p => true, the results returned by the service will not be filtered, and we can test that the provider correctly delegates the work to the service, and doesn’t filter the data.

[TestMethod]
public void WhenIFilterOnAgeGT36ThenTheProviderDoesntFilter()
{
    LambdaBasedPeopleFinder peopleFinder =
        new LambdaBasedPeopleFinder(p => true);
    PeopleFinderLocator.Instance = peopleFinder;

    QueryableServiceData<Person> people =
        new QueryableServiceData<Person>();

    var query = people
        .Where(p => p.Age >= 36);

    var results = query.ToList();

    Assert.IsFalse(results.All(p => p.Age >= 36));
    Assert.AreEqual(
        new IntCriterion()
        {
            FilterType = NumericFilterType.IsGreaterThan,
            Value = 36
        },
        peopleFinder.PassedCriteria.Age);
}

Finally, testing the provider was not a complicated question. My problem was not “how to test”, but rather “what to test”.

To finish, here are the next things that I want to do about this project :

  • Use SpecFlow to transform all my tests and use the Gherkin syntax,
  • Handle more complex queries, list all the type of nodes that can be found and handle them, ensuring the correctness of the returned data. If needed, any unhandled node type would result in using a blank SearchCriteria object and performing all the work using Linq to Objects,
  • Implement the service, even if it’s not necessary, just for the sake of it,
  • Get stuck manipulating expression tress,
  • Push the whole thing to a Github repository,
  • Get help from anyone motivated.
Posted in LINQ | Tagged , , , | Comments Off

Linq provider : an attempt… part 5

Improving the toolbox : building our own expression tree visualizations

In the last two posts, I included sample visualizations of expression trees. I’ve built these using a visitor pattern, that produces HTML markup. This is a good example of the use of this pattern, so I’ll try to explain how it allows us to work with expression trees.

The expression tree visualization that I build is based on HTML / CSS3, using the code provided at http://thecodeplayer.com/walkthrough/css3-family-tree. Basically, the markup is formed of unordered lists (“ul / li” tags) that contains nested lists. You can view the generated HTML source by inspecting the DOM in the previous post.

The visualization builder is a class called TreeVisualizer, inheriting from ExpressionVisitor :

internal class TreeVisualizer : ExpressionVisitor { private StringBuilder builder; private HtmlTextWriter writer; private TreeVisualizer() { this.builder = new StringBuilder(); this.writer = new HtmlTextWriter( new StringWriter( this.builder, CultureInfo.InvariantCulture), " "); } [...]

The constructor is private, the only way to use this class is through a static method called BuildVisualization :

internal static string BuildVisualization(Expression expression)
{
    TreeVisualizer visualizer = new TreeVisualizer();
    visualizer.Visit(expression);
    return visualizer.Visualization;
}

The returned property, Visualization, is defined this way :

public string Visualization
{
    get
    {
        return this.builder.ToString();
    }
}

The class uses also two utility methods :

  • GetSimplifiedType, which gives a user-friendly string representation of a given type.
private string GetSimplifiedType(Type type)
{
    if (!type.IsGenericType)
        return type.Name;

    string genericName = type.Name.Split('`').First();

    string genericArguments = string.Join(
        ", ",
        type.GenericTypeArguments.Select(
            t => GetSimplifiedType(t)));

    return string.Format(
        "{0}<{1}>",
        genericName,
        genericArguments);
}
  • VisitAndBuildTree, which adds content to the HtmlTextWriter based on the tree nodes that it visits :
private Expression VisitAndBuildTree(
    string nodeName,
    string nodeType,
    string nodeDescription,
    Func<Expression> childrenVisitorFunction = null)
{
    this.writer.RenderBeginTag("li");
    this.writer.WriteLine();
    this.writer.Indent++;

    this.writer.AddAttribute("href", "#");
    this.writer.RenderBeginTag("a");

    this.writer.AddAttribute("class", "node-name");
    this.writer.RenderBeginTag("span");
    this.writer.WriteEncodedText(nodeName);
    this.writer.RenderEndTag();
    this.writer.WriteBreak();

    if (!string.IsNullOrEmpty(nodeType))
    {
        this.writer.AddAttribute("class", "node-type");
        this.writer.RenderBeginTag("span");
        this.writer.WriteEncodedText(nodeType);
        this.writer.RenderEndTag();
        this.writer.WriteBreak();
    }

    this.writer.WriteEncodedText(nodeDescription);
    this.writer.RenderEndTag();
    this.writer.WriteLine();

    Expression baseReturn = null;
    if (childrenVisitorFunction != null)
    {
        this.writer.RenderBeginTag("ul");
        this.writer.WriteLine();
        this.writer.Indent++;

        baseReturn = childrenVisitorFunction();

        this.writer.Indent--;
        this.writer.RenderEndTag();
        this.writer.WriteLine();

    }

    this.writer.Indent--;
    this.writer.RenderEndTag();
    this.writer.WriteLine();

    return baseReturn;
}

With the two previous functions, we can now override each VisitSomeTypeOfNode method and insert the appropriate details in the HTML. For instance :

protected override Expression VisitBinary(
    BinaryExpression node)
{
    return VisitAndBuildTree(
        "Binary",
        string.Empty,
        node.NodeType.ToString(),
        () => base.VisitBinary(node));
}
protected override Expression VisitLambda<T>(
    Expression<T> node)
{
    return VisitAndBuildTree(
        "Lambda",
        GetSimplifiedType(node.Type),
        node.ToString(),
        () => base.VisitLambda<T>(node));
}
protected override Expression VisitMethodCall(
    MethodCallExpression node)
{
    return VisitAndBuildTree(
        "Call",
        GetSimplifiedType(node.Type),
        node.Method.Name,
        () => base.VisitMethodCall(node));
}

There are many methods, I’m not going to show them all here. I’ll just finish with a special one, VisitConstant. For this one, I just handled two special cases, when the constant is an IEnumerable, or when it is a string. This allows us to see the constants values for simple types in the tree, and a simplified type description if it is a generic IEnumerable.

protected override Expression VisitConstant(
    ConstantExpression node)
{
    string type = GetSimplifiedType(node.Type);

    string value;
    if (node.Type.IsGenericType
        && node.Type.FindInterfaces(
            (t, o) => t.Name.StartsWith("IEnumerable"),
            true).Any())
    {
        value = type;
    }
    else if(type == "String")
    {
        value = string.Concat(
            "\"",
            ((string)node.Value).Replace("\"", "\\\""),
            "\"");
    }
    else
    {
        value = node.Value.ToString();
    }

    VisitAndBuildTree(
        "Constant",
        type,
        value);
    return base.VisitConstant(node);
}

That’s all for tonight !

Posted in LINQ | Tagged , , , , , | Comments Off