Roman Pelepei gives smart answers on questions about C# .Net, ASP .Net, WPF and Silverlight programming with examples and source code.
среда, 14 декабря 2011 г.
How to write fluent interface with C# and Lambda.
Last week I had a nice discussion in the office about “how to write fluent interface” and I have found a couple of articles over the internet about that. As usual I disagree with some of them and, as usual, my friend Mauro Servienti (MVP C#) has a nice article about it, unfortunately in Italian. He just gave me the startup input.
If you think about the Fluent Interface, it is just a trick that you use with C# in order to cheat the intellisense of Visual Studio and in order to create a nice style for your code. Of course there is a specific way to write fluent interface.
Let’s make a short sample. The classic Person class and the factory pattern.
We have a class which represents the Person Entity and has some common properties.
Very easy. Now, in a normal world you would have something like this, in order to create a new instance of a class person.
This code is classic and very verbose. If you want to use it the syntax would be something like this:
var person = PersonFactory.CreatePerson("Raffaele", string.Empty,"Garofalo");
Now, if we want to add an address to this person we need an additional like of code like this one, and of course a new factory for the class person or a new method in the person factory … whatever …
var address = PersonFactory.CreateAddress("1st Lane", "Main Road","Hamilton", "Bermuda", "HM10");
First of all, here we have a big problem. All the parameters are strings. So, if we don’t explain in a proper verbose way each parameter, the developer that will use our factory won’t be able to know what to write in each parameter. Second thing, if we don’t use C# 4 we have to specify each parameter value anyway … Finally we are avoiding a nice readability in our code.
The first step for a fluent interface.
I saw a lot of code around the web but a lot of people forget about the name of this technique … The name is Fluent Interface so this means that probably we should add some interfaces in our code in order to have a good result. Well VS 2010 is able to create an interface from a class just with a couple of clicks … And this is the final result:
Now we need to translate each method in a Fluent method. Let’s start with the class person. What I am doing is an interface for my Factory and two methods, one for the Factory initialization, where we initialize a new instance of the class person and one to finalize it where we will return the current instance of that class. Of course we need also the methods to add some values to the person properties. Look at the UML:
So now we start to have a FluentInterface capability in our code.
var person = newPersonFactory()
// we can skip this line now ...
Very well done but we still have a problem here. We are not giving a constraint to the developer that will use our fluent syntax. Let’s say that we are working with a retarded colleague, nobody can prohibit him to write something like this:
var wrongPerson = newPersonFactory().Create();
In this case he will get a nice NullReferenceException because if he doesn’t call the method Initialize the factory won’t create a new instance of the class person … So how can we add a constraint to our interface? Very simple, we need 3 interfaces and not only one anymore. We need IInitFactory, IPersonFactory and ICreateFactory.
Let’s see the code:
IPersonFactory AddFirstName(string firstName);
IPersonFactory AddLastName(string lastName);
IPersonFactory AddMiddleName(string middleName);
The IPersonFactory now will not be in charge anymore of creating a new instance of the class person, it will just be in charge of working with it. We will use dependency injection to inject a new instance. Let’s the concrete implementation of this factory:
Now we need an orchestrator. Somebody that will be visible outside and will be in charge of giving to the fluent syntax a static flavor (we want to avoid the new Factory() syntax …) and that will return a PersonFactory ready to work …
Person Fluent Factory
And now Visual Studio will follow our rules …
Final Step, Lamba expression for a cool syntax.
Ok this is cool and it works like we want but … it is really time consuming. We want a fluent interface and that’s fine but if you a domain with 100 entities and more or less 100 factories, can you imagine the pain in the neck in order to adopt this pattern all over?? Well this is the reason you should study more in depth C#!! If you didn’t know, there is a cool syntax future in C# called Lambda Expressions. If you don’t know what I am talking about have a look here.
First of all we need a generic interface for our factory with only two methods, one to add a value to a property and one to return the current instance of the entity created by the factory.