Question

I need that, using a builder like the next code ...

var foo = FooBuilder
          .WithSomething()
          .WithOtherthing();

or

var foo = FooBuilder
          .WithOtherthing()
          .WithSomething();

works as follows:

var foo = FooBuilder
          .WithSomething()
          .WithOtherthing()
          .Build();

i.e. make the Build method as default, I knew that there is a way but I forgot it. Thanks in advance.

Was it helpful?

Solution

Well, I wouldn't actually recommend it, but the closest you could come would be to have an implicit conversion operator from FooBuilder to Foo:

public static implicit operator Foo(FooBuilder builder)
{
    return builder.Build();
}

However, you'd then need to make your variable explicitly typed:

Foo foo = FooBuilder
             .WithSomething()
             .WithOtherthing();

It's not clear whether you actually meant new FooBuilder() here when you just wrote FooBuilder, by the way. I personally prefer to create builders with settable properties, which allows you to use object initializers. For example:

// With the implicit conversion from FooBuilder to Foo
Foo foo = new FooBuilder { Name = "Fred", Value = 10 };

// Without the implicit conversion
var foo = new FooBuilder { Name = "Fred", Value = 10 }.Build();

This is assuming you actually want a separate FooBuilder type. If you're happy creating a new instance of Foo for each "pseudo-mutation" then you can use jure's option. Personally I like the separate Build approach, as it means you can perform validation just at the end, which means you don't need to worry about the ordering of operations where validation depends on multiple related properties.

For example, if you had a type with DayOfMonth and Month properties, and you wanted to change from "January 30th" to "February 20th" then in the "create a new validated object on each step" you'd need to change the day of month first, then the month... but if you were going from "February 20th" to "January 30th" you'd have to do it the other way round. The approach using a separate builder type and a single Build call which validates everything at the end means you don't need to worry.

OTHER TIPS

If you are creating your own builder interface, you can achieve something similar with extension methods to the class you are building

public static class FooExtensions
{
  public static Foo WithSomething(this Foo foo)
  {
    //do your thing with foo
    ....

    return foo;
  }

  public static Foo WithOtherthing(this Foo foo)
  {
     //do your thing with foo
    ....

     return foo;
  }
}

and then use it as

  var foo = new Foo().WithSomething().WithOtherthing();

FluentBuilder with such behaviour is achieved with extension methods

public static class FluentBuilder
{
    public static Foo Build()
    {
        return new Foo();
    }

    public static Foo WithSomething(this Foo foo)
    {
        foo.Something = new Something();
        return foo;
    }

    public static Foo WithOtherThing(this Foo foo)
    {
        foo.OtherThing = new OtherThing();
        return foo;
    }
}

Usage:

var foo1 = FluentBuilder.Build();
var foo2 = FluentBuilder.Build().WithSomething().WithOtherThing();
var foo3 = FluentBuilder.Build().WithOtherThing().WithSomething();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top