Skip to content

Instantly share code, notes, and snippets.

@robdmoore
Last active December 29, 2015 12:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robdmoore/7671127 to your computer and use it in GitHub Desktop.
Save robdmoore/7671127 to your computer and use it in GitHub Desktop.
NTestDataBuilder with inheritance within the classes being built
// Simpler, but you get all methods and get's unwieldy as the number of differences between the / number of sub classes grows
using System;
using NTestDataBuilder;
namespace ConsoleApplication4
{
class Program
{
static void Main()
{
var sports = ObjectMother.Cars.Sport
.WithExhaust(ExhaustSize.UberBig)
.WithName("Red Ferrari")
.Build();
Console.WriteLine("{0}: exhaust {1}", sports.Name, sports.Exhaust);
var boring = ObjectMother.Cars.Boring
.WithSpeed(Speed.Slow)
.WithName("Grey VW Beetle")
.Build();
Console.WriteLine("{0}: speed {1}", boring.Name, boring.Speed);
Console.ReadLine();
}
}
public abstract class Car
{
protected Car(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class BoringCar : Car
{
public BoringCar(string name, Speed speed)
: base(name)
{
Speed = speed;
}
public Speed Speed { get; private set; }
}
public enum Speed
{
Slow,
VerySlow,
UltraSlow
}
public class SportsCar : Car
{
public SportsCar(string name, ExhaustSize exhaust)
: base(name)
{
Exhaust = exhaust;
}
public ExhaustSize Exhaust { get; private set; }
}
public enum ExhaustSize
{
Big,
ReallyBig,
UberBig
}
class CarBuilder<TCar> : TestDataBuilder<TCar, CarBuilder<TCar>> where TCar : Car
{
public CarBuilder()
{
Set(x => x.Name, "A car");
Set(x => (x as BoringCar).Speed, Speed.UltraSlow);
Set(x => (x as SportsCar).Exhaust, ExhaustSize.ReallyBig);
}
public CarBuilder<TCar> WithName(string name)
{
Set(x => x.Name, name);
return this;
}
public CarBuilder<TCar> WithSpeed(Speed speed)
{
if (typeof (TCar) == typeof (BoringCar))
{
Set(x => (x as BoringCar).Speed, speed);
}
return this;
}
public CarBuilder<TCar> WithExhaust(ExhaustSize exhaust)
{
if (typeof(TCar) == typeof(SportsCar))
{
Set(x => (x as SportsCar).Exhaust, exhaust);
}
return this;
}
protected override TCar BuildObject()
{
if (typeof (TCar) == typeof (BoringCar))
return new BoringCar(Get(x => x.Name), Get(x => (x as BoringCar).Speed)) as TCar;
if (typeof(TCar) == typeof(SportsCar))
return new SportsCar(Get(x => x.Name), Get(x => (x as SportsCar).Exhaust)) as TCar;
throw new NotSupportedException(string.Format("Invalid TCar in CarBuilder: {0}", typeof(TCar).Name));
}
}
static class ObjectMother
{
public static class Cars
{
public static CarBuilder<SportsCar> Sport
{
get
{
return new CarBuilder<SportsCar>();
}
}
public static CarBuilder<BoringCar> Boring
{
get
{
return new CarBuilder<BoringCar>();
}
}
}
}
}
// More generic magic, but a much more maintainable solution
using System;
using NTestDataBuilder;
namespace ConsoleApplication4
{
class Program
{
static void Main()
{
var sports = ObjectMother.Cars.Sport
.WithExhaust(ExhaustSize.UberBig)
.WithName("Red Ferrari")
.Build();
Console.WriteLine("{0}: exhaust {1}", sports.Name, sports.Exhaust);
var boring = ObjectMother.Cars.Boring
.WithSpeed(Speed.Slow)
.WithName("Grey VW Beetle")
.Build();
Console.WriteLine("{0}: speed {1}", boring.Name, boring.Speed);
Console.ReadLine();
}
}
public abstract class Car
{
protected Car(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class BoringCar : Car
{
public BoringCar(string name, Speed speed)
: base(name)
{
Speed = speed;
}
public Speed Speed { get; private set; }
}
public enum Speed
{
Slow,
VerySlow,
UltraSlow
}
public class SportsCar : Car
{
public SportsCar(string name, ExhaustSize exhaust)
: base(name)
{
Exhaust = exhaust;
}
public ExhaustSize Exhaust { get; private set; }
}
public enum ExhaustSize
{
Big,
ReallyBig,
UberBig
}
abstract class CarBuilder<TCar, TBuilder> : TestDataBuilder<TCar, TBuilder>
where TCar : Car
where TBuilder : CarBuilder<TCar, TBuilder>
{
protected CarBuilder()
{
Set(x => x.Name, "A car");
}
protected TBuilder This()
{
return this as TBuilder;
}
public TBuilder WithName(string name)
{
Set(x => x.Name, name);
return This();
}
}
class SportsCarBuilder : CarBuilder<SportsCar, SportsCarBuilder>
{
public SportsCarBuilder()
{
Set(x => x.Exhaust, ExhaustSize.ReallyBig);
}
public SportsCarBuilder WithExhaust(ExhaustSize exhaust)
{
Set(x => x.Exhaust, exhaust);
return this;
}
protected override SportsCar BuildObject()
{
return new SportsCar(Get(x => x.Name), Get(x => x.Exhaust));
}
}
class BoringCarBuilder : CarBuilder<BoringCar, BoringCarBuilder>
{
public BoringCarBuilder()
{
Set(x => x.Speed, Speed.UltraSlow);
}
public BoringCarBuilder WithSpeed(Speed speed)
{
Set(x => x.Speed, speed);
return this;
}
protected override BoringCar BuildObject()
{
return new BoringCar(Get(x => x.Name), Get(x => x.Speed));
}
}
static class ObjectMother
{
public static class Cars
{
public static SportsCarBuilder Sport
{
get
{
return new SportsCarBuilder();
}
}
public static BoringCarBuilder Boring
{
get
{
return new BoringCarBuilder();
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment