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