Last active
June 29, 2020 05:50
-
-
Save jansabbe/78d624c053e44843c2c3a173e682c22e to your computer and use it in GitHub Desktop.
Generic With method builder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using System.Reflection; | |
using Xunit; | |
namespace Tjoelala | |
{ | |
public class Person | |
{ | |
public string Name { get; private set; } | |
public string FirstName { get; set; } | |
public string FullName => $"{FirstName} {Name}"; | |
public int Age { get; set; } | |
public List<Person> Kids { get; private set; } = new List<Person>(); | |
private Person() { } | |
public Person(string name) | |
{ | |
Name = name; | |
} | |
} | |
public class PersonBuilder : ObjectBuilder<Person, PersonBuilder> | |
{ | |
public PersonBuilder() | |
{ | |
With(x => x.Name, "Bos") | |
.With(x => x.FirstName, "Jos") | |
.With(x => x.Age, 44); | |
} | |
public PersonBuilder WithKids(int nbOfKids) | |
{ | |
var kids = Enumerable.Range(0, nbOfKids) | |
.Select(i => new PersonBuilder() | |
.With(t => t.FirstName, $"kid{i}") | |
.With(t => t.Age, 14) | |
.Build()) | |
.ToList(); | |
return With(t => t.Kids, kids); | |
} | |
} | |
public class UnitTest1 | |
{ | |
[Fact] | |
public void Test1() | |
{ | |
var person = new PersonBuilder() | |
.With(t => t.FirstName, "Albert") | |
.With(t => t.Name, "Bosje") | |
.WithKids(3) | |
.Build(); | |
Assert.Equal("Albert Bosje", person.FullName); | |
Assert.Equal(3, person.Kids.Count); | |
} | |
} | |
#region Object builder stuff | |
public abstract class ObjectBuilder<TObject, TBuilder> where TBuilder : ObjectBuilder<TObject, TBuilder> where TObject : class | |
{ | |
private readonly Dictionary<PropertyInfo, object> _values = new Dictionary<PropertyInfo, object>(); | |
public virtual TObject Build() | |
{ | |
var obj = Activator.CreateInstance(typeof(TObject), true) as TObject; | |
foreach (var kvp in _values) | |
{ | |
var pi = kvp.Key; | |
var value = kvp.Value; | |
pi.SetValue(obj, value); | |
} | |
return obj; | |
} | |
public TBuilder With<TProp>(Expression<Func<TObject, TProp>> expr, TProp value) | |
{ | |
var body = expr.Body as MemberExpression; | |
var property = body.Member as PropertyInfo; | |
_values[property] = value; | |
return this as TBuilder; | |
} | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment