I'll show a problem by example. There is a base class with fluent interface:
class FluentPerson { private string _FirstName = String.Empty; private string _LastName = String.Empty; public FluentPerson WithFirstName(string firstName) { _FirstName = firstName; return this; } public FluentPerson WithLastName(string lastName) { _LastName = lastName; return this; } public override string ToString() { return String.Format("First name: {0} last name: {1}", _FirstName, _LastName); } }
and a child class:
class FluentCustomer : FluentPerson { private long _Id; private string _AccountNumber = String.Empty; public FluentCustomer WithAccountNumber(string accountNumber) { _AccountNumber = accountNumber; return this; } public FluentCustomer WithId(long id) { _Id = id; return this; } public override string ToString() { return base.ToString() + String.Format(" account number: {0} id: {1}", _AccountNumber, _Id); } }
The problem is that when you call customer.WithAccountNumber("000").WithFirstName("John").WithLastName("Smith")
you can't add .WithId(123)
in the end because return type of the WithLastName()
method is FluentPerson (not FluentCustomer).
How this problem usually solved?
Try to use some Extension methods.
static class FluentManager { public static T WithFirstName<T>(this T person, string firstName) where T : FluentPerson { person.FirstName = firstName; return person; } public static T WithId<T>(this T customer, long id) where T : FluentCustomer { customer.ID = id; return customer; } } class FluentPerson { public string FirstName { private get; set; } public string LastName { private get; set; } public override string ToString() { return string.Format("First name: {0} last name: {1}", FirstName, LastName); } } class FluentCustomer : FluentPerson { public long ID { private get; set; } public long AccountNumber { private get; set; } public override string ToString() { return base.ToString() + string.Format(" account number: {0} id: {1}", AccountNumber, ID); } }
after you can use like
new FluentCustomer().WithId(22).WithFirstName("dfd").WithId(32);
You can use generics to achieve that.
public class FluentPerson<T> where T : FluentPerson<T> { public T WithFirstName(string firstName) { // ... return (T)this; } public T WithLastName(string lastName) { // ... return (T)this; } } public class FluentCustomer : FluentPerson<FluentCustomer> { public FluentCustomer WithAccountNumber(string accountNumber) { // ... return this; } }
And now:
var customer = new FluentCustomer() .WithAccountNumber("123") .WithFirstName("Abc") .WithLastName("Def") .ToString();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With