Validating Shift class through builder pattern
Don't be mad at me because I will again suggest you a different approach than your current implementation that exists in .Net for exactly that purpose, this is, validating models ;-)

But first a few comments about this one.

The ShiftBuilder requires a collection of validators to build the object IEnumerable&lt;IShiftValidator&gt;. This is a good start because you can use various validations however the current ones don't follow this principle yet. The example you showed has two responsibilities, this means it validates two things:


if (shiftToValidate.Duration.TotalMinutes &lt;= 0)
{
    FailedValidationException = new ArgumentOutOfRangeException(nameof(shiftToValidate.Duration));
    FailedValidationMessage = "Shift's duration cant be less than 1 minute.";
    return false;
}
if (shiftToValidate.Duration.TotalHours &gt; SharedSettings.MaximumShiftHours)
{
    FailedValidationException =
        new ArgumentOutOfRangeException(nameof(shiftToValidate.Duration));
    FailedValidationMessage = "Shift's duration cant be longer than the maximum allowed hours.";
    return false;
}



There are two ifs where each can fail. This means you need to split this validator into more specific one to test only one condition at a time.



Other then this I find this is a very complex implementation that leads me to the alternative suggestion which uses the ValidationAttribute. C# already has a system for constructing model validations. Here's a small example.

You can create a bunch of custom attributes that you use to decorate the properties of the Shift class with.

public class Shift
{
    public string Name { get; private set; }
    public TimeSpan StartHour { get; private set; }

    [GreaterThen(nameof(StartHour))]
    public TimeSpan EndHour { get; private set; }

    [GreaterThenZero]
    public TimeSpan Duration =&gt; EndHour - StartHour;

    public Shift()
    {
        // Just an example to make the validation fail.
        StartHour = TimeSpan.FromSeconds(100);
        EndHour = TimeSpan.FromSeconds(50);
    }
}


There are various ways of implementing them so you'll need to read more about them to know all options. I show you one of them where they implement the IsValid method in a very generic way (might not be perfect yet but it should make the point).

So you may need one attribute to validate the Duration:

public class GreaterThenZeroAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        return
            ((IComparable)value).CompareTo((IComparable)TimeSpan.FromSeconds(0)) &gt; 0
                ? ValidationResult.Success
                : new ValidationResult($"{validationContext.MemberName} must be greater then zero");
    }
}


but on the other hand if you add GreaterThenAttribute the GreaterThenZeroAttribute for the Duration is no longer necessary. 

public class GreaterThenAttribute : ValidationAttribute
{
    private readonly string _otherPropertyName;
    public GreaterThenAttribute(string otherPropertyName)
    {
        _otherPropertyName = otherPropertyName;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var otherProperty = 
            validationContext
                .ObjectType
                .GetProperty(_otherPropertyName)
                .GetValue(validationContext.ObjectInstance);

        return
            ((IComparable)value).CompareTo((IComparable)otherProperty) &gt; 0
                ? ValidationResult.Success
                : new ValidationResult($"{validationContext.MemberName} must be greater then {_otherPropertyName}");
    }
}


You may however need a new attribute for


shiftToValidate.Duration.TotalHours &gt; SharedSettings.MaximumShiftHours



to make sure the duration does not exceed a certain number like MaxHoursFromSettings etc. and you can read the actual value from the settings later.

Finally to invoke the validation you use the Validator

var shift = new Shift();
Validator.ValidateObject(shift, new ValidationContext(shift), true);