Alex James, PM on EF, publish sometimes some C# posts.
He published a post to explain how to “link” the methods call.
To realize it, he returns the instance in his methods:
public abstract class PropertyConfiguration
{
private bool _nullable;
public virtual PropertyConfiguration Nullable()
{
_nullable = true;
return this;
}
public virtual PropertyConfiguration NonNullable()
{
_nullable = false;
return this;
}
}
public class StringPropertyConfiguration : PropertyConfiguration
{
private int? _maxLength;
public StringPropertyConfiguration MaxLength(int maxLength)
{
_maxLength = maxLength;
return this;
}
}
With this way, he can do:
var nameConfiguration = new StringPropertyConfiguration()
.MaxLength(100)
.Nullable();
But the following code doesn’t compile:
var nameConfiguration = new StringPropertyConfiguration()
.Nullable()
.MaxLength(100);
The idea of Damien Guard (one of the last MS guy who works on LINQ to SQL) was to use the extension methods:
public abstract class PropertyConfiguration
{
private bool _nullable;
public bool Nullable
{
get { return _nullable; }
set { _nullable = value; }
}
}
public static class PropertyConfigurationExtension
{
public static T Nullable<T>(this T propertyConfiguration) where T: PropertyConfiguration
{
propertyConfiguration.Nullable = true;
return propertyConfiguration;
}
}
Cool!
Now the question is: is it possible to do it with C#2 (so without extension methods)?
For this, I suggest the following solution:
public abstract class PropertyConfiguration<T> where T : PropertyConfiguration<T>
{
private bool _nullable;
public virtual T Nullable()
{
_nullable = true;
return (T)this;
}
public virtual T NonNullable()
{
_nullable = false;
return (T)this;
}
}
public class StringPropertyConfiguration : PropertyConfiguration<StringPropertyConfiguration>
{
private int? _maxLength;
public StringPropertyConfiguration MaxLength(int maxLength)
{
_maxLength = maxLength;
return this;
}
}
This one is more complex but is interesting because I give the type of the derived class to the base class using generics.
The problem with this approach is the fact that it isn’t possible to use directly the base class (ie to have a parameter of type PropertyConfiguration or a List of PropertyConfiguration) because of the generics. To fix it, we can use an interface:
public interface IPropertyConfiguration
{
IPropertyConfiguration Nullable();
IPropertyConfiguration NonNullable();
}
public abstract class PropertyConfiguration<T> : IPropertyConfiguration where T : PropertyConfiguration<T>
{
private bool _nullable;
public virtual T Nullable()
{
_nullable = true;
return (T)this;
}
public virtual T NonNullable()
{
_nullable = false;
return (T)this;
}
IPropertyConfiguration IPropertyConfiguration.Nullable()
{
return Nullable();
}
IPropertyConfiguration IPropertyConfiguration.NonNullable()
{
return NonNullable();
}
}
Enjoy 