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

Monday, 19 January 2009

Refactored: Fluent Test Data Builders Using Generic Extension Methods and Lambda Expressions

Working further with the Fluent Test Data Builder I was working on yesterday has led me to refactor what I had, and the result is, I think, even nicer!

I've added a new method SetValue, and changed the from getting the Member.Name to getting the PropertyInfo from the Member. The other significant change is that I'm now wrapping the SetLength and SetValue methods in try catch blocks so that I can intercept a TargetInvocationException and throw the InnerException in its place, this helps to ensure that when I use the ExpectedExceptionAttribute I am catching the exception I really expect. The drawback with this is the stack trace, but I'm content to live with that for now.

publicstatic T SetLength<T>(this T obj, Expression<Func<T, string>> expression, int length)
{
try
    {
        PropertyInfo member = getMemberExpressionMember(expression.Body);
        string currentValue = expression.Compile().Invoke(obj) ?? string.Empty;
        string newValue = currentValue.PadRight(length);

        member.SetValue(obj, newValue, null);

        return obj;
    }

    catch (TargetInvocationException tie)
    {
        if (tie.InnerException != null) throw tie.InnerException;
        throw;
    }
}
 
public static TObj SetValue<TObj, TVal>(this TObj obj, Expression<Func<TObj, TVal>> expression, TVal value)
{

    try
    {
        PropertyInfo member = getMemberExpressionMember(expression.Body);
        member.SetValue(obj, value, null);
        return obj;
    }
    catch (TargetInvocationException tie)
    {
        if (tie.InnerException != null) throw tie.InnerException;
        throw;
    }
}



So how am I making use of this fluent interface? Well the methods above are two of those I have written, and probably the most interesting, but I have others too. These fall into two main categories:



  1. setting default valid values;

  2. creating default valid objects.


For setting default valid values, these are done as ExtensionMethods on the type I'm interested in. For example:



        public static Extract WithDefaultTitle(this Extract extract)
        {
            extract.QualificationTitle = "Mr";
            extract;
        }


For creating default valid objects, this is also done with an ExtensionMethod on the type that I'm interested in. As my need for different default starting points increases then I can easily write more. Here's an example:


        public static Extract AsValid(this Extract extract)
        {
            return extract
                .WithDefaultCode()
                .WithDefaultTitle()
                .SetValue(e => e.Id, 111)
        }


With these methods available to me I can combine them with my SetValue and SetLength methods to then alter the state of any given property so that I can test the implications of the value set in a degree of isolation (at least consistency).  In particular I am using this to test that behaviour to validate my object works correctly given different combinations of property values on the object under test. Here's an example of this:


        [Test]
        [ExpectedException(typeof(InvalidOperationException), "An Id must be present.")]
        public void NullIdShouldThrowAnInvalidOperationExceptionOnValidate()
        {
            Extract extract = new Extract()
                .AsValid()
                .SetValue(e => e.Id, null);
            extract.Validate();
        }
 
        [Test]
        public void A_SurnameWithLessThan35CharactersShouldBePaddedTo35CharactersInFormattedProperties()
        {
            Extract extract = new Extract()
                .AsValid()
                .SetLength(e => e.Surname, 34);
                
            Assert.AreEqual(34, extract.Surname.Length);
            Assert.AreEqual(35, extract.FormattedProperties["Surname"].Length);
        }

Personally I'm happy with how this is progressing, but we'll see how it goes as I begin to push the current envelope a bit more.

Sunday, 18 January 2009

Fluent Test Data Builders Using Generic Extension Methods and Lambda Expressions

Whilst writing some extension methods this evening to make creating objects in unit tests simpler I found myself writing methods that looked sufficiently similar to each other that I felt the code lacked a little DRYness.

The code being written has to output a data extract in a fixed field length formatted text file. As such the length of the formatted fields is very important, so I had created some methods to initialise the properties of my object with given lengths so that I could ensure the desired behaviour during formatting (such as trimming, padding, exception throwing, etc...). These methods looked much like this:

public static DataExtract WithSetLengthSurname(this DataExtract dataExtract, int length) 
{ 
    dataExtract.Surname = string.Empty.PadRight(length); 
    return dataExtract; 
}
 
public static DataExtract WithSetLengthForenames(this DataExtract dataExtract, int length) 
{ 
    dataExtract.Forenames = string.Empty.PadRight(length); 
    return dataExtract; 
} 
 

As you can see these methods are very similar. What I wanted I felt was to take this fluent interface for creating my DataExtract object, but to make the whole thing more generic.


This is what I came up with:


public static T SetLength<T>(this T obj, Expression<Func<T,string>> expression, int length) 
{ 
    string memberName = getMemberExpressionMemberName(expression.Body); 
    string currentValue = expression.Compile().Invoke(obj) ?? string.Empty; 
    string newValue = currentValue.PadRight(length); 
    obj.GetType().GetProperty(memberName).SetValue(obj, newValue, null); 
    return obj; 
} 
 
private static string getMemberExpressionMemberName (Expression expression) 
{ 
    if (expression == null) return string.Empty; 
 
    switch (expression.NodeType) 
    { 
        case ExpressionType.MemberAccess: 
            { 
                MemberExpression memberExpression = (MemberExpression) expression; 
                return memberExpression.Member.Name; 
            } 
        default: 
            throw new InvalidOperationException(string.Format("The Expression Type was not expected: {0}", expression.NodeType)); 
    } 
 
}

With this code then I can now make a call like this:


DataExtract extract = new DataExtract().SetLength((e) => e.Forenames, 10);

Now it's not unreasonable to look at this and wonder what has been gained, after all I could have written this:


DataExtract extract = new DataExtract { Forenames = "".PadRight(10) };

I suppose for me it comes into its own when combined with other extension methods as a part of a wider ranging Fluent Interface based test object builder, like this:


CandidateExtract extract = new CandidateExtract() 
    .SetLength((e) => e.Surname, 36) 
    .WithValidQualificationCode() 
    .WithValidQualificationTitle() 
    .SetLength((e) => e.Forenames, 36);

As can be seen in the above some property specific methods still exist, because the behaviour that each implements is sufficiently unique, but where the behaviour is very similar (such as setting a string to a default length) this seems to me to provide a number of benefits:


  • the number of methods appearing in Intellisense drops making it easier to find what you want quickly
  • the number of builder methods to be written drops (in my case significantly)
  • by using a fluent interface readability is enhanced.

Thursday, 19 June 2008

Resharper 4.0 and Lambda Expressions

Now I'm fairly new to the wonderful world of Resharper, so barely a day goes by where I don't discover something new about it, or through it. But today I found a feature that just made me want to share about it straight away.

Let me set the scene.

I'm coding a Lambda expression for use as a predicate and when finished I notice the now familiar little light bulb. Hmmm I thought, now what could Resharper be wanting to tell me about my code?

Resharper offers conversion from Lambda to statement, and to anonymous method.(real code replaced throughout to protect the innocent)

That's right Resharper is offering to convert my Lambda to either an anonymous method or a statement! So let's see what it does to the code if I choose these options.

Well If I choose the option 'Lambda expression to statement it turns my code into this:

The same code as inline statement.Note with this option I am given the choice to now convert on to an expression, or to an anonymous method.

If I choose the option 'To anonymous method' my code looks like this:

The same code as anonymous method. Note that it is offering to convert my code back to a lambda

If I choose the 'Lambda expression to anonymous method' option and place the caret in to the delegate keyword then I get a different option however.

Different Resharper options with the anonymous method.

This time the options include one to convert my anonymous method to a named method. Choosing this does what you will no doubt expect. It creates named method.

private static bool NewPredicate(Person p)
{ return p.Name == "Sue"; }

and changes my code to read:

Person sue = people.Find(NewPredicate);

Actually I added the prefix new, as Resharper just put Predicate, but you get the idea. Of course, Resharper now gives me the option to inline my Predicate as either an anonymous method, or as a Lambda.

Resharper offering to inline my named delegate method.

Neat huh!

Choosing to inline as an anonymous method acts as I would expect, and puts the code back to be the same as the anonymous version above. Choosing to inline as a Lambda however a have a tiny, tiny gripe with.

Resharper offering to remove the 'redundant parenthesis' that it inserted.

As you can see above, Resharper has placed the target variable within brackets. Still, at least Resharper knows that it shouldn't have done this, as it offers to remove them!

What I really, really like most about this, and made me want to blog about it, it that it very neatly highlights some of the evolution of C# from version 1 with its' named delegates (though of course we didn't have delegate comparisons then), through version 2, with its' anonymous methods, through to the current version 3 with its' Lambda goodness.

Tuesday, 3 June 2008

Using TextFieldParser objects and the My library in C# code

I read this article on InfoQ (a great site for information for those that don't know it) and saw that there might be some confusion about whether this useful class could be used in C# projects. The answer of course is yes. Just reference the Microsoft.VisualBasic dll in your project and away you go.

The My library is a little different it does a whole bunch of different things, providing both new methods, and a simplified model for accessing things that are both in the framework and that are specific to the project being worked in. For the new methods reflecting on the Microsoft.VisualBasic assembly soon uncovers these, and from there they can then just be referenced as above (or fronted with a simple facade if you prefer - perhaps extension methods FileInfo.OpenTextFieldParser() anyone). For the simplified navigation of the framework, and project, feature I don't know how that can be done in C#, but why would you want to? You know the framework anyway, right?

Sunday, 18 May 2008

Extension Methods - My new best friend*

No that doesn't mean that I'm going to be [ab]using extension methods everywhere - though I suspect that extension methods could become the new singleton. That said I think that I am really starting to get them. Here's an example.

Last night I'm doing some coding and I want to get some objects that I have written to serialise nicely to Xml. Now I don't want to give them public constructors as they sit within an aggregate, and should only be constructed by the Factory for that aggregate. Also I want to exercise quite a lot of control over the XML that is written. This being the case the use of the XmlSerializer class is pretty much unacceptable to me (see, it's not just because I resent spelling it with a 'z').

Now, pre C# 3.0 I would normally have a method in a helper class somewhere with a method that looked a bit like this.

public static XmlAttribute CreateAttribute(XmlDocument xmlDocument, string name, string value)
{
XmlAttribute newAttribute = xmlDocument.CreateAttribute(name);
newAttribute.Value = value;
return newAttribute;
}

Leaving aside that Helper classes offend me somewhat (if you want to know why then read this book). It would be much nicer if the XmlElement class just had an AppendAttribute method with the suitable overloads which would both create the attribute for me and append it to the element. Well, thanks to the power of extension methods this is very easy to do. Just look at the code below.

public static void AppendAttribute(this System.Xml.XmlElement xmlElement, string name, string value)
{
XmlAttribute newAttribute = xmlElement.OwnerDocument.CreateAttribute(name);
newAttribute.Value = value;
xmlElement.Attributes.Append(newAttribute);
}

public static void AppendAttribute(this System.Xml.XmlElement xmlElement, string prefix, string localName, string namespaceURI, string value)
{
XmlAttribute newAttribute = xmlElement.OwnerDocument.CreateAttribute(prefix, localName, namespaceURI);
newAttribute.Value = value;
xmlElement.Attributes.Append(newAttribute);
}

With this I now just have to make this single, easy, call when I want to add an attribute to an element:

newElement.AppendAttribute("id", _id);

Nice, eh!

* Girlfriend excluded