Skip to content

Instantly share code, notes, and snippets.

@rootn3rd
Created February 4, 2020 18:25
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 rootn3rd/97cc2731e668a7f5d0bcec77d79b8d23 to your computer and use it in GitHub Desktop.
Save rootn3rd/97cc2731e668a7f5d0bcec77d79b8d23 to your computer and use it in GitHub Desktop.
Fluent API Builder Quirks
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace BuilderPattern
{
class Program
{
static void Main(string[] args)
{
RunBuilderExample2();
Console.WriteLine("Done!!");
}
private static void RunBuilderExample2()
{
Adventurer dink = Adventurer.Create
.WithName("Some name")
.WithSex(Sex.Female)
.WithHP(100)
.Stats
.Assign(a => a.Stats.Intelligence, 80)
.Assign(a => a.Stats.Strength, 10)
.Build();
Console.WriteLine(dink);
}
}
public interface IAdventurerBuilder
{
IAdventurerBuilder WithName(string name);
IAdventurerBuilder WithSex(Sex sex);
IAdventurerBuilder WithHP(int hp);
IAdventurerStatsBuilder Stats { get; }
Adventurer Build();
}
public interface IAdventurerStatsBuilder : IAdventurerBuilder
{
IAdventurerStatsBuilder Assign<TProp>(Expression<Func<Adventurer, TProp>> statSelector, int value);
}
public enum Sex { Male, Female }
public class Adventurer
{
private Adventurer() { }
public Stats Stats { get; set; } = new Stats();
public string Name { get; set; }
public int HitPoints { get; set; }
public Sex Sex { get; set; }
public static IAdventurerBuilder Create => new AdventureBuilderImpl();
private class AdventureBuilderImpl : IAdventurerBuilder
{
protected Adventurer adventurer = new Adventurer();
public IAdventurerStatsBuilder Stats => new AdventureStatsBuilderImpl(adventurer);
public Adventurer Build()
{
return adventurer;
}
public IAdventurerBuilder WithHP(int hp)
{
adventurer.HitPoints = hp;
return this;
}
public IAdventurerBuilder WithName(string name)
{
adventurer.Name = name;
return this;
}
public IAdventurerBuilder WithSex(Sex sex)
{
adventurer.Sex = sex;
return this;
}
}
private class AdventureStatsBuilderImpl : AdventureBuilderImpl, IAdventurerStatsBuilder
{
//private Adventurer adventurer;
public AdventureStatsBuilderImpl(Adventurer adventurer) => this.adventurer = adventurer;
public IAdventurerStatsBuilder Assign<TProp>(Expression<Func<Adventurer, TProp>> statSelector, int value)
{
// a => a.Stats.Intelligence
PropertyInfo property = ((MemberExpression)statSelector.Body).Member as PropertyInfo;
property.SetValue(adventurer.Stats, value);
return this;
}
}
public override string ToString()
{
return $"Name : {Name} | Gender : {Sex.ToString()} | HitPoints : {HitPoints} | Stats : I-{Stats.Intelligence}/S-{Stats.Strength}";
}
}
public class Stats
{
public int Intelligence { get; set; }
public int Strength { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment