Okay, so I'm having a carstarter installed in my car and obviously have nothing better to do than keep tinkering with this DSL stuff.
So I'm thinking... If we create a DSL for the person writing the code, then the debug experience should also be DSL-like. Now I'm not about to write my own debugger, but instead of showing a plain DateTime (what kind of datatype is that anyway?!?!?) we're talking animals, persons and real 'talk' date of birth stuff here.
So I create a special DateOfBirth class which overrides the ToString() method and this creates a 'pretty' experience in my debug window. Notice the values for DateOfBirth. This could ofcourse be extended to person, which is still displayed as the same old school type information: 'DSL.Person'.

The complete code comes at the end of this post, but lets have a look at te code complexity when going from
Person p = new Person();
p.DateOfBirth = new DateTime(1972,9,25);
to our DSL 

I guess the code is not too bad. Visual Studio still scores it green on the maintainability scale, but it is clear that quite a large amount of code is needed to create a DSL. And DSL's like this get more context sensitive. Imagine if I would also like to support birds with my DSL? Birds get hatched not born. I'd have to expand my extensions class, or maybe create a whole new set of classes and methods, having a class 'HatchedOn'.
Anyway, they just called, my car is done.
Here is the code for the final sample:
namespace DSL
{
class Program
{
static void Main(string[] args)
{
Person mark = Person.Named("Mark").BornOn(Day.the25th).Of(Month.September).InTheYear(1972);
Animal watson = Animal.Named("Watson").BornOn(Day.the2nd).Of(Month.January).InTheYear(2001).AndItIsA(Animal.KindOf.Dog);
}
}
public class DateOfBirth
{
public int Year;
public Month Month;
public Day Day;
public static implicit operator DateTime(DateOfBirth dob)
{
return new DateTime(dob.Year, (int)dob.Month, (int)dob.Year);
}
public override string ToString()
{
return "Born on " + Day.ToString() + " of " + Month.ToString() + " in the year " + Year.ToString() + ".";
}
}
public enum Day : int
{
the1st = 1,
the2nd = 2,
the25th = 25
}
public enum Month : int
{
January = 1,
February = 2,
September = 9
}
public interface IDateOfBirth
{
DateOfBirth DateOfBirth { get; set; }
}
public class Person : IDateOfBirth
{
public DateOfBirth DateOfBirth { get; set; }
public string Name { get; set; }
public static Person Named(string name)
{
Person p = new Person(name);
p.DateOfBirth = new DateOfBirth();
return p;
}
protected Person(string name)
{
Name = name;
}
}
public class Animal : IDateOfBirth
{
public enum KindOf
{
Dog,
Cat
}
public DateOfBirth DateOfBirth { get; set; }
public string Name { get; set; }
public KindOf KindOfAnimal { get; set; }
public static Animal Named(string name)
{
Animal animal = new Animal();
animal.Name = name;
animal.DateOfBirth = new DateOfBirth();
return animal;
}
public Animal AndItIsA(KindOf kind)
{
KindOfAnimal = kind;
return this;
}
}
public static class DateOfBirthExtensions
{
public static T BornOn<T>(this T p, Day day) where T : IDateOfBirth
{
p.DateOfBirth.Day = day;
return p;
}
public static T Of<T>(this T p, Month month) where T : IDateOfBirth
{
p.DateOfBirth.Month = month;
return p;
}
public static T InTheYear<T>(this T p, int year) where T : IDateOfBirth
{
p.DateOfBirth.Year = year;
return p;
}
}
}