Fluent interfaces in C#

The topic of the contracts definition and how the programmer can do it in the safest way and guarantee that who will use the contract will do that in the right way is a common and complex argument.

In the development phase the preconditions are fundamentals to check that the parameters allowed in our contract are satisfied and we can help us the guard clauses:

public class Person
{
private string _firstName;
private string _lastName;

public void SetFirstName(string firstName)
{
if (string.IsNullOrEmpty(firstName))
{
throw new ArgumentException("message", nameof(firstName));
}

_firstName = firstName;
}

public void SetLastName(string lastName)
{
if (string.IsNullOrEmpty(lastName))
{
throw new ArgumentException("message", nameof(lastName));
}

_lastName = lastName;
}
}

In this case we have a Person class and we define some preconditions when an external user try to set the first name and/or the last name.

But what we can do if we want, for example, calculate the fullname of the person object and we want to ensure that both the first name and the last name are filled up?

In this case one of the possible solution is implementing some specific interfaces an a builder that deal with this work.

Interfaces

We firstly define some contracts for the Person class:


public interface ISetFirstName
{
ISetLastName SetFirstName(string firstName);
}

public interface ISetLastName
{
IPerson SetLastName(string lastName);
}

public interface IPerson
{
string FullName { get; }
}

Now the Person class needs to implement these interfaces:


public class Person : ISetFirstName, ISetLastName, IPerson
{
internal Person() {}

public string FullName => _firstName + " " + _lastName;
private string _firstName;
private string _lastName;

public ISetLastName SetFirstName(string firstName)
{
if (string.IsNullOrEmpty(firstName)) throw new ArgumentNullException();

_firstName = firstName;
return this;
}

public IPerson SetLastName(string lastName)
{
if (string.IsNullOrEmpty(lastName)) throw new ArgumentNullException();

_lastName = lastName; return this;
}
}

We have the public FullName property, the FirstName and the LastName setters.

At the moment, no one user is able to create a Person object outside the assembly, because the Person class has an internal constructor; this is a protection, I want the users to be able to create objects with another class, a person builder.

Builder

This is the implementation of the Person builder:

public class PersonBuilder
{
public ISetFirstName Person { get; }

public PersonBuilder()
{
Person = new Person();
}
}

Now we can create a Person object:

var builder = new PersonBuilder();
var person = builder.Person.SetFirstName("Mirko").SetLastName("Maggioni");
var fullname = person.FullName;

As you can see, this is a clean way to define and use this specific type of contract.

The definition of the interfaces might appear sligthly verbose, but we will have to use it only with this type of requirement.

 

One thought on “Fluent interfaces in C#

Add yours

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: