How to make a Build method as default to be invoked in a C# builder fluent interface

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

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

или же

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

работает следующим образом:

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

ie make the Build method as default, I knew that there is a way but I forgot it. Заранее спасибо.

3 ответа

Решение

Ну, я бы на самом деле не рекомендовал бы это, но самое близкое, что вы могли бы прийти, это иметь неявный оператор преобразования изFooBuilderвFoo:

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

Однако тогда вам нужно будет сделать вашу переменную явно набранной:

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

Не ясно, имел ли ты в виду new FooBuilder() здесь, когда вы только что написали FooBuilder, Кстати. Я лично предпочитаю создавать компоновщики с настраиваемыми свойствами, что позволяет использовать инициализаторы объектов. Например:

// 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();

Это предполагает, что вы на самом деле хотите отдельный FooBuilder тип. Если вы счастливы, создавая новый экземпляр Foo для каждой "псевдомутации" вы можете использовать параметр jure. Лично мне нравится отдельный Build подход, так как это означает, что вы можете выполнить проверку только в конце, что означает, что вам не нужно беспокоиться о порядке операций, когда проверка зависит от нескольких связанных свойств.

Например, если у вас был тип с DayOfMonth а также Month свойства, и вы хотели изменить с "30 января" на "20 февраля", а затем в "создать новый проверенный объект на каждом шаге", вам нужно сначала изменить день месяца, а затем месяц... но если вы шли с "20 февраля" на "30 января", вам нужно было бы сделать это наоборот. Подход с использованием отдельного типа построителя и одного Build вызов, который проверяет все в конце, означает, что вам не нужно беспокоиться.

Если вы создаете свой собственный интерфейс разработчика, вы можете достичь чего-то похожего с помощью методов расширения для класса, который вы создаете

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;
  }
}

а затем использовать его как

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

FluentBuilder с таким поведением достигается с помощью методов расширения

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;
    }
}

Использование:

var foo1 = FluentBuilder.Build();
var foo2 = FluentBuilder.Build().WithSomething().WithOtherThing();
var foo3 = FluentBuilder.Build().WithOtherThing().WithSomething();
Другие вопросы по тегам