В общем по следам этого вопроса решил написать примерчик, но к сожалению не осилил 😢. Может кто из вас поможет дописать 😉. Имеем такой класс человека class Person { public Person(string firstName, string lastName, Address address, Employment employment) { FirstName = firstName LastName = lastName Address = address Employment = employment } public string FirstName { get } public string LastName { get } public Address Address { get } public Employment Employment { get } public override string ToString() { return $"{FirstName} {LastName}: " + Environment.NewLine + $"{Address}" + Environment.NewLine + $"{Employment}" } } с сопутствующими классами class Address { public string City { get set } public int PostCode { get set } public override string ToString() { return $"Адрес: {City}-{PostCode} " } } class Employment { public string CompanyName { get set } public string Position { get set } public int AnnualIncome { get set } public override string ToString() { return $"Работа: {CompanyName}, должность: {Position}, зарплата: {AnnualIncome}" } } Самостоятельно удалось написать только такой строитель class PersonBuilder { //аккумулятор названий свойств и их значений private readonly Dictionary _propertiesToBuild public PersonBuilder() { _propertiesToBuild = new Dictionary() } //запоминание в словаре названия свойства и его значения public PersonBuilder Set(Expression> expression, T value) { var propertyName = ((MemberExpression)expression.Body).Member.Name _propertiesToBuild.Add(propertyName, value) return this } public T Include(Expression> expression) { var propertyName = ((MemberExpression)expression.Body).Member.Name if (propertyName == nameof(Person.Address)) { var result = new Address() return (T)(object)result } else { var result = new Employment() return (T)(object)result } } //создание экземпляра на основе значений свойств из словаря public Person Build() { return new Person ( firstName: GetPropertyValue(nameof(Person.FirstName), "Неизвестно"), lastName: GetPropertyValue(nameof(Person.LastName), "Неизвестно"), address: new Address(), employment: new Employment() ) } private T GetPropertyValue(string propertyName, T defaultValue) { return _propertiesToBuild.TryGetValue(propertyName, out var value) ? (T)value : defaultValue } } И пока это работает так var person = new PersonBuilder() .Set(p => p.FirstName, "Андрей") .Set(p => p.LastName, "Иванов") .Build() или так Address address = new PersonBuilder() .Set(p => p.FirstName, "Андрей") .Set(p => p.LastName, "Иванов") .Include(p => p.Address) ну или так Employment employment = new PersonBuilder() .Set(p => p.FirstName, "Андрей") .Set(p => p.LastName, "Иванов") .Include(p => p.Employment) А хотелось бы в результате как-то так Person person = new PersonBuilder() .Set(p => p.FirstName, "Андрей") .Set(p => p.LastName, "Иванов") .Include(p => p.Address) .Set(a => a.City, "Москва") .Include(p => p) .Include(p => p.Employment) .Set(e => e.Position, "инженер") .Include(p => p) .Build() P.S. получившейся в итоге вариант здесь, спасибо @Vasek
Ответ В качестве пропаганды всего нового и хорошего напомню, что immutable + builder из коробки поддерживается 9-ой версией C#. Добавляем в .csproj 9.0, и ваш пример можно магически записать следующим образом: record Person { public string FirstName { get init } public string LastName { get init } public Address Address { get init } public Employment Employment { get init } public override string ToString() => $"{FirstName} {LastName}: {Address} {Employment}" } record Address { public string City { get init } public int PostCode { get init } public override string ToString() => $"Адрес: {City}-{PostCode}" } record Employment { public string CompanyName { get init } public string Position { get init } public int AnnualIncome { get init } public override string ToString() => $"Работа: {CompanyName}, должность: {Position}, зарплата: {AnnualIncome}" } А код, использующий всё это, запишется так: var person = new Person() with { FirstName = "Андрей" } with { LastName = "Иванов" } with { Address = new Address() with { City = "Мюнхен" } with { PostCode = 80000 } } with { Employment = new Employment() with { CompanyName = "Google" } with { Position = "CEO" } with { AnnualIncome = 100500 } } Всё!