Last active
January 6, 2024 14:32
-
-
Save schwastek/6a2c6e846823ebd4cf2fd7af21758d46 to your computer and use it in GitHub Desktop.
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; | |
namespace BuilderWithImplicitConversion; | |
// Usage | |
public class Program | |
{ | |
static void Main(string[] args) | |
{ | |
// Builder pattern usage with `Build()` method call omitted thanks to implicit operator | |
User user = new UserBuilder() | |
.WithFirstName("John") | |
.WithLastName("Doe") | |
.WithAge(25) | |
.WithAuthentication( | |
new AuthenticationBuilder() | |
.WithUsername("jdoe") | |
.WithPassword("password123") | |
); | |
Console.WriteLine($"User: {user.FirstName}, {user.LastName}, {user.Age}"); | |
Console.WriteLine($"Authentication: {user.Authentication?.Username}, {user.Authentication?.Password}"); | |
// Real-world example usage when setting up data for test fixture | |
user = TestHelper.BuildUserWithAuthentication(userBuilder => userBuilder.WithFirstName("Jane")); | |
Console.WriteLine($"User: {user.FirstName}, {user.LastName}, {user.Age}"); | |
} | |
} | |
// Builders | |
public class UserBuilder : BaseBuilder<User> | |
{ | |
protected override User Instance { get; } = new(); | |
public UserBuilder WithFirstName(string firstName) | |
{ | |
Instance.FirstName = firstName; | |
return this; | |
} | |
public UserBuilder WithLastName(string lastName) | |
{ | |
Instance.LastName = lastName; | |
return this; | |
} | |
public UserBuilder WithAge(int age) | |
{ | |
Instance.Age = age; | |
return this; | |
} | |
public UserBuilder WithAuthentication(Authentication authentication) | |
{ | |
Instance.Authentication = authentication; | |
return this; | |
} | |
} | |
public class AuthenticationBuilder : BaseBuilder<Authentication> | |
{ | |
protected override Authentication Instance { get; } = new(); | |
public AuthenticationBuilder WithUsername(string username) | |
{ | |
Instance.Username = username; | |
return this; | |
} | |
public AuthenticationBuilder WithPassword(string password) | |
{ | |
Instance.Password = password; | |
return this; | |
} | |
} | |
public abstract class BaseBuilder<T> where T : class | |
{ | |
protected abstract T Instance { get; } | |
// Implicit conversion from `BaseBuilder<T>` to the final `T` object | |
public static implicit operator T(BaseBuilder<T> builder) | |
{ | |
return builder.Build(); | |
} | |
public virtual T Build() | |
{ | |
return Instance; | |
} | |
} | |
// Models | |
public class Authentication | |
{ | |
public string? Username { get; set; } | |
public string? Password { get; set; } | |
} | |
public class User | |
{ | |
public string? FirstName { get; set; } | |
public string? LastName { get; set; } | |
public int Age { get; set; } | |
public Authentication? Authentication { get; set; } | |
} | |
public static class TestHelper | |
{ | |
public static User BuildUserWithAuthentication(Action<UserBuilder>? userBuilder = null) | |
{ | |
// Default user | |
UserBuilder user = new UserBuilder() | |
.WithFirstName("John") | |
.WithLastName("Doe") | |
.WithAge(25) | |
.WithAuthentication( | |
new AuthenticationBuilder() | |
.WithUsername("john") | |
.WithPassword("password123") | |
); | |
// Apply overrides if any | |
userBuilder?.Invoke(user); | |
return user.Build(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment