views:

1111

answers:

12

"Fluent interfaces" is a fairly hot topic these days. C# 3.0 has some nice features (particularly extension methods) that help you make them.

FYI, a fluent API means that each method call returns something useful, often the same object you called the method on, so you can keep chaining things. Martin Fowler discusses it with a Java example here. The concept kooks something like this:

var myListOfPeople = new List<Person>();

var person = new Person();
person.SetFirstName("Douglas").SetLastName("Adams").SetAge(42).AddToList(myListOfPeople);

I have seen some incredibly useful fluent interfaces in C# (one example is the fluent approach for validating parameters found in an earlier StackOverflow question I had asked. It blew me away. It was able to give highly readable syntax for expressing parameter validation rules, and also, if there were no exceptions, it was able to avoid instantiating any objects! So for the "normal case", there was very little overhead. This one tidbit taught me a huge amount in a short time. I want to find more things like that).

So, I'd like to learn more by looking at and discussing some excellent examples. So, what are some excellent fluent interfaces you've made or seen in C#, and what made them so valuable?

Thanks.

+1  A: 

The new HttpClient of the WCF REST Starter Kit Preview 2 is a great fluent API. see my blog post for a sample http://bendewey.wordpress.com/2009/03/14/connecting-to-live-search-using-the-httpclient/

bendewey
Great! I'm looking at it right now. Thanks.
Charlie Flowers
bendewey ... was wondering your opinion of this: could they have made it not fluent just as well, or do you think there was a particular reason in this case that it needed to be fluent?
Charlie Flowers
If you look at the code its actually quite simple. The fluency, comes mostly from extension methods, which, I've been sceptical of, but when used to enhance this fluency I'm for it.
bendewey
I did look at it. It's definitely an example of a fluent interface. Thanks for pointing it out.
Charlie Flowers
+7  A: 

This is actually the first time I've heard the term "fluent interface." But the two examples that come to mind are LINQ and immutable collections.

Under the covers LINQ is a series of methods, most of which are extension methods, which take at least one IEnumerable and return another IEnumerable. This allows for very powerful method chaining

var query = someCollection.Where(x => !x.IsBad).Select(x => x.Property1);

Immutable types, and more specifically collections have a very similar pattern. Immutable Collections return a new collection for what would be normally a mutating operation. So building up a collection often turns into a series of chained method calls.

var array = ImmutableCollection<int>.Empty.Add(42).Add(13).Add(12);
JaredPar
I like the immutable collection example.
Charlie Flowers
+1 totally overlooked linq thats a huge one. I just heard the term fluent interface the day before this question.
bendewey
A problem with that immutable collection syntax, especially in a loop, is that it works the same as concatenating strings - exponential run time - better to fill a normal collection and then wrap/copy it into the immutable just once. Concept is nice though.
devstuff
@devstuff, you're making an assumption about the underlying nature of the collection. Not all immutable collections require a copy operation in order to add elements (linked lists, finger trees, etc ...). Sure, using an ImmutableArray would have this problem but it's not a failure of all types
JaredPar
You know, this would be nice for a Builder for an immutable collection. There is a period where the collection is mutable while you are "constructing" it, but when you finish, it becomes immutable. Much like using StringBuilder for a while, then turning it into a string. But fluently.
Charlie Flowers
@Charlie, in that case though, why not use a normal mutable collection and then translate it into an immutable version?
JaredPar
That's basically the idea behind Freezables.
Erik Forbes
@JaredPar, yeah that's really what I meant. You create some object that is mutable, and then call several operations on it. Then, you've got it defined, so you ask it to build you an immutable. Useful for immutables that need several steps to specify. And fluent seems appealing for that case.
Charlie Flowers
+1  A: 

The Criteria API in NHibernate has a nice fluent interface which allows you to do cool stuff like this:

Session.CreateCriteria(typeof(Entity))
    .Add(Restrictions.Eq("EntityId", entityId))
    .CreateAlias("Address", "Address")
    .Add(Restrictions.Le("Address.StartDate", effectiveDate))
    .Add(Restrictions.Disjunction()
        .Add(Restrictions.IsNull("Address.EndDate"))
        .Add(Restrictions.Ge("Address.EndDate", effectiveDate)))
    .UniqueResult<Entity>();
lomaxx
What's it going to do with that? Turn it into sql?
Charlie Flowers
yeah, then return an Entity object
lomaxx
+1  A: 

i liked this one discussed here on SO:

fluent interface for html

That is a meaty StackOverflow question, with some meaty answers. Thanks.
Charlie Flowers
+2  A: 

SubSonic 2.1 has a decent one for the query API:

DB.Select()
  .From<User>()
  .Where(User.UserIdColumn).IsEqualTo(1)
  .ExecuteSingle<User>();

tweetsharp makes extensive use of a fluent API too:

var twitter = FluentTwitter.CreateRequest()
              .Configuration.CacheUntil(2.Minutes().FromNow())
              .Statuses().OnPublicTimeline().AsJson();

And Fluent NHibernate is all the rage lately:

public class CatMap : ClassMap<Cat>  
{  
  public CatMap()  
  {  
    Id(x => x.Id);  
    Map(x => x.Name)  
      .WithLengthOf(16)  
      .Not.Nullable();  
    Map(x => x.Sex);  
    References(x => x.Mate);  
    HasMany(x => x.Kittens);  
  }  
}

Ninject uses them too, but I couldn't find an example quickly.

John Sheehan
A: 

As @John Sheehan mentioned, Ninject uses this type of API to specify bindings. Here are some example code from their user guide:

Bind<IWeapon>().To<Sword>();
Bind<Samurai>().ToSelf();
Bind<Shogun>().ToSelf().Using<SingletonBehavior>();
Tormod Fjeldskår
+5  A: 

I love the fluent interface in CuttingEdge.Conditions.

From their sample:

 // Check all preconditions:
 id.Requires("id")
    .IsNotNull()          /* throws ArgumentNullException on failure /
    .IsInRange(1, 999)    / ArgumentOutOfRangeException on failure /
    .IsNotEqualTo(128);   / throws ArgumentException on failure */
 

I've found that it is a lot easier to read, and makes me much more effective at checking my preconditions (and post conditions) in methods than when I have 50 if statements to handle the same checks.

Reed Copsey
Cool. I hadn't come across that library yet. I'll check it out.
Charlie Flowers
It's a very nice one. I've been happy using it so far.
Reed Copsey
I personally don't like Requires("id")... why they didn't use EnsureThat() or something similar without ugly strings. Oh, I know, probably to make exceptions more explanatory. but still.
lubos hasko
There's a great way to avoid having to use string but still get the name of the parameter into your error message (which is a string of course). See here: http://stackoverflow.com/questions/669678/what-is-the-smoothest-most-appealing-syntax-youve-found-for-asserting-parameter/670495#670495
Charlie Flowers
The string is for better exception messages. They actually don't require "id" in there, but I find I don't mind so much. There are other options, including using expression trees or reflection, but they all have some issues, especially if you obfuscate your code.
Reed Copsey
@Reed, that's the main point I was making ... the approach I pointed to can still have the good exception message with the name, even though you don't have to have a string in your code. But, as you said, it uses expression trees.
Charlie Flowers
Regarding the use of strings, I argued with the author of CuttingEdge.Conditions that we should use the technique described by Charlie Flowers above so that we don't have to use strings. The author rejected the idea, saying the creation of an expression tree is too expensive.
Judah Himango
What we really need is nameof(someField) operator in C#.
Judah Himango
I agree that nameOf and some similar operators would be great. Let us get to the names of variables that are in scope cheaply so that there is less of a barrier between code and data.
Charlie Flowers
+4  A: 

Kudos for the method parameter validation, you've given me a new idea for our fluent APIs. I've hated our precondition checks anyways...

I've built a extensibility system for a new product in development, where you can fluently describe the commands available, the user interface elements and more. This runs on top of StructureMap and FluentNHibernate, which are nice APIs too.

MenuBarController mb;
// ...
mb.Add(Resources.FileMenu, x =>
{
  x.Executes(CommandNames.File);
  x.Menu
    .AddButton(Resources.FileNewCommandImage, Resources.FileNew, Resources.FileNewTip, y => y.Executes(CommandNames.FileNew))
    .AddButton(null, Resources.FileOpen, Resources.FileOpenTip, y => 
    {
      y.Executes(CommandNames.FileOpen);
      y.Menu
        .AddButton(Resources.FileOpenFileCommandImage, Resources.OpenFromFile, Resources.OpenFromFileTop, z => z.Executes(CommandNames.FileOpenFile))
        .AddButton(Resources.FileOpenRecordCommandImage, Resources.OpenRecord, Resources.OpenRecordTip, z => z.Executes(CommandNames.FileOpenRecord));
     })
     .AddSeperator()
     .AddButton(null, Resources.FileClose, Resources.FileCloseTip, y => y.Executes(CommandNames.FileClose))
     .AddSeperator();
     // ...
});

And you can configure all commands available like this:

Command(CommandNames.File)
  .Is<DummyCommand>()
  .AlwaysEnabled();

Command(CommandNames.FileNew)
  .Bind(Shortcut.CtrlN)
  .Is<FileNewCommand>()
  .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileSave)
  .Bind(Shortcut.CtrlS)
  .Enable(WorkspaceStatusProviderNames.DocumentOpen)
  .Is<FileSaveCommand>();

Command(CommandNames.FileSaveAs)
  .Bind(Shortcut.CtrlShiftS)
  .Enable(WorkspaceStatusProviderNames.DocumentOpen)
  .Is<FileSaveAsCommand>();

Command(CommandNames.FileOpen)
  .Is<FileOpenCommand>()
  .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileOpenFile)
  .Bind(Shortcut.CtrlO)
  .Is<FileOpenFileCommand>()
  .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileOpenRecord)
  .Bind(Shortcut.CtrlShiftO)
  .Is<FileOpenRecordCommand>()
  .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Our view configure their controls for the standard edit menu commands using a service given to them by the workspace, where they just tell it to observe them:

Workspace
  .Observe(control1)
  .Observe(control2)

If the user tabs to the controls, the workspace automatically gets an appropriate adapter for the control and provides undo/redo and clipboard operations.

It has helped us reduce the setup code dramatically and make it even more readable.


I forgot to tell about a library we're using in our WinForms MVP model presenters to validate the views: FluentValidation. Really easy, really testable, really nice!

__grover
That is some excellent stuff. You've made a DSL for menus and commands ... and a good one from the looks of it. What does Is<T> do? Such as Is<FileOpenRecordCommand>()?
Charlie Flowers
It associates a command type (a class implementing the command pattern) with a logical command name (a string). Every invocation uses a a new instance of the type.This way extensions can invoke commands using names without explicitly knowing who/where is actually implementing them.
__grover
Oh, got it. Nice.
Charlie Flowers
Oh yes, FluentValidation looks very nice. Especially When and Unless. Again, its a highly readable DSL. Thanks for the link.
Charlie Flowers
(I already gave you +1, I'd give you more if I could:) Of course, there is the "accepted response", which you're the front-runner for right now.
Charlie Flowers
I love these DSLs and fluent APIs ;)
__grover
+3  A: 

In addition to the ones specified here, the popuplar RhinoMocks unit test mock framework uses fluent syntax to specify expectations on mock objects:

// Expect mock.FooBar method to be called with any paramter and have it invoke some method
Expect.Call(() => mock.FooBar(null))
    .IgnoreArguments()
    .WhenCalled(someCallbackHere);

// Tell mock.Baz property to return 5:
SetupResult.For(mock.Baz).Return(5);
Judah Himango
+1  A: 

Method Naming

Fluent interfaces lend themselves to readability as long as the method names are chosen sensibly.

With that in mind, I'd like to nominate this particular API as "anti-fluent":

System.Type.IsInstanceOfType

It's a member of System.Type and takes an object, and returns true if the object is an instance of the type. Unfortunately, you naturally tend to read it from left to right like this:

o.IsInstanceOfType(t);  // wrong

When it's actually the other way:

t.IsInstanceOfType(o);  // right, but counter-intuitive

But not all methods could possibly be named (or positioned in the BCL) to anticipate how they might appear in "pseudo-English" code, so this isn't really a criticism. I'm just pointing out another aspect of fluent interfaces - the choosing of method names in order to cause the least surprise.

Object Initializers

With many of the examples given here, the only reason a fluent interface is being used is so that several properties of a newly allocated object can be initialized within a single expression.

But C# has a language feature that very often makes this unnecessary - object initializer syntax:

var myObj = new MyClass
            {
                SomeProperty = 5,
                Another = true,
                Complain = str => MessageBox.Show(str),
            };

This perhaps would explain why expert C# users are less familiar with the term "fluent interface" for chaining calls on the same object - it isn't needed quite so often in C#.

As properties can have hand-coded setters, this is an opportunity to call several methods on the newly constructed object, without having to make each method return the same object.

The limitations are:

  • A property setter can only accept one argument
  • A property setter cannot be generic

I would like it if we could call methods and enlist in events, as well as assign to properties, inside an object initializer block.

var myObj = new MyClass
            {
                SomeProperty = 5,
                Another = true,
                Complain = str => MessageBox.Show(str),
                DoSomething()
                Click += (se, ev) => MessageBox.Show("Clicked!"),
            };

And why should such a block of modifications only be applicable immediately after construction? We could have:

myObj with
{
    SomeProperty = 5,
    Another = true,
    Complain = str => MessageBox.Show(str),
    DoSomething(),
    Click += (se, ev) => MessageBox.Show("Clicked!"),
}

The with would be a new keyword that operates on an object of some type and produces the same object and type - note that this would be an expression, not a statement. So it would exactly capture the idea of chaining in a "fluent interface".

So you could use initializer-style syntax regardless of whether you'd got the object from a new expression or from an IOC or factory method, etc.

In fact you could use with after a complete new and it would be equivalent to the current style of object initializer:

var myObj = new MyClass() with
            {
                SomeProperty = 5,
                Another = true,
                Complain = str => MessageBox.Show(str),
                DoSomething(),
                Click += (se, ev) => MessageBox.Show("Clicked!"),
            };

And as Charlie points out in the comments:

public static T With(this T with, Action<T> action)
{
    if (with != null)
        action(with);
    return with;
}

The above wrapper simply forces a non-returning action to return something, and hey presto - anything can be "fluent" in that sense.

Equivalent of initializer, but with event enlisting:

var myObj = new MyClass().With(w =>
            {
                w.SomeProperty = 5;
                w.Another = true;
                w.Click += (se, ev) => MessageBox.Show("Clicked!");
            };

And on a factory method instead of a new:

var myObj = Factory.Alloc().With(w =>
            {
                w.SomeProperty = 5;
                w.Another = true;
                w.Click += (se, ev) => MessageBox.Show("Clicked!");
            };

I couldn't resist giving it the "maybe monad"-style check for null as well, so if you have something that might return null, you can still apply With to it and then check it for null-ness.

Daniel Earwicker
You could do something like this. Make an extension method on Object called "With". Let it take a Func<T>, and pass the object into the Func. Now, whatever lambda you pass it will execute inside the context of the object. Pretty cool really.
Charlie Flowers
That's logically exactly what I want (although it should be an Action, not a Func). Okay, so the syntax is messier, but I'll take something I can use over an imaginary/unlikely language extension! :)
Daniel Earwicker
Yes, the null check inside With is a nice touch. Let's you keep being fluent even if there's a null.
Charlie Flowers
+2  A: 
Charlie Flowers
Wow! That's really cool... I always thought the only way to do this i reflection. In fact, I'm going to go refactor some stuff right now.
Jacob
Wouldn't `void WriteProperty(Expression<Func<object>> expr)´ work for the impossible example?
erikkallen
No, that only works for **one** parameter. I want to output many properties to the console, without retyping "ConsoleHelper.WriteProperty" each time. So first I tried params, but if they aren't all the same type, that doesn't work. Fluent let me keep syntax small while dumping many properties out.
Charlie Flowers
A: 

I really like FI pattern. I just posted two blogs on reading data for domain objects.

David.Chu.ca