Skip to content

Builder 妯″紡鐢熸垚鍣?

椤圭洰浣嶇疆

05-BuilderGenerator/

瀛︿範鐩爣

  • 鐞嗚В Builder 璁捐妯″紡
  • 鐢熸垚宓屽绫荤粨鏋?
  • 瀹炵幇娴佺晠鎺ュ彛锛團luent Interface锛?
  • 澶勭悊娉涘瀷鍜岀害鏉?
  • 瀹炵幇楠岃瘉閫昏緫
  • 鏀寔涓嶅彲鍙樺璞?
  • 鐢熸垚澶嶆潅鐨勪唬鐮佺粨鏋?

瀛︿範濡備綍鐢熸垚宓屽绫诲拰娴佺晠鎺ュ彛锛屽疄鐜板鏉傜殑浠g爜缁撴瀯鐢熸垚銆?

浠€涔堟槸 Builder 妯″紡锛?

Builder锛堝缓閫犺€咃級妯″紡鏄竴绉嶅垱寤哄瀷璁捐妯″紡锛屽畠鍏佽浣犱娇鐢ㄩ摼寮忚皟鐢ㄧ殑鏂瑰紡閫愭鏋勫缓澶嶆潅瀵硅薄銆?

Builder 妯″紡缁撴瀯

浼犵粺鏂瑰紡 vs Builder 妯″紡:

csharp
// 浼犵粺鏂瑰紡锛氫娇鐢ㄥ璞″垵濮嬪寲鍣?
var person = new Person
{
    Name = "寮犱笁",
    Age = 30,
    Email = "zhangsan@example.com"
};

// Builder 妯″紡锛氶摼寮忚皟鐢?
var person = Person.CreateBuilder()
    .WithName("寮犱笁")
    .WithAge(30)
    .WithEmail("zhangsan@example.com")
    .Build();

宸ヤ綔娴佺▼

Builder 妯″紡鐨勪紭鍔?

  • 鍙鎬у己: 姣忎釜鏂规硶鍚嶆竻妤氬湴琛ㄦ槑浜嗘鍦ㄨ缃粈涔堝睘鎬?
  • 鐏垫椿鎬ч珮: 鍙互鎸変换鎰忛『搴忚缃睘鎬?
  • 绫诲瀷瀹夊叏: 缂栬瘧鏃舵鏌ワ紝IDE 鎻愪緵瀹屾暣鐨勬櫤鑳芥彁绀?
  • **涓嶅彲鍙樺璞?*: 鍙互鐢ㄤ簬鏋勫缓涓嶅彲鍙樺璞?
  • 楠岃瘉闆嗕腑: 鍙互鍦?Build() 鏂规硶涓泦涓繘琛岄獙璇?

鐢熸垚鍣ㄥ疄鐜?

鐢熸垚鍣ㄤ細涓烘瘡涓爣璁扮殑绫荤敓鎴愪互涓嬬粨鏋勶細

csharp
partial class Person
{
    public class Builder
    {
        private string _name;
        private int _age;
        
        public Builder WithName(string value)
        {
            _name = value;
            return this;  // 杩斿洖 this 鏀寔閾惧紡璋冪敤
        }
        
        public Person Build()
        {
            return new Person
            {
                Name = _name,
                Age = _age
            };
        }
    }
    
    public static Builder CreateBuilder()
    {
        return new Builder();
    }
}

鍏抽敭鎶€鏈?

1. 宓屽绫荤敓鎴?

鐢熸垚宓屽绫婚渶瑕佹纭鐞嗙缉杩涘拰鍛藉悕绌洪棿锛?

csharp
sb.AppendLine($"namespace {classInfo.Namespace}");
sb.AppendLine("{");
sb.AppendLine($"    partial class {classInfo.ClassName}");
sb.AppendLine("    {");
sb.AppendLine($"        public class Builder");
sb.AppendLine("        {");
// ... Builder 绫诲唴瀹?
sb.AppendLine("        }");
sb.AppendLine("    }");
sb.AppendLine("}");

2. 娴佺晠鎺ュ彛

娴佺晠鎺ュ彛鐨勫叧閿槸姣忎釜鏂规硶杩斿洖 this锛?

csharp
public Builder WithName(string value)
{
    _name = value;
    return this;  // 杩斿洖 Builder 瀹炰緥
}

3. 璇婃柇鍜岄敊璇鐞?

csharp
if (!classInfo.IsPartial)
{
    var diagnostic = Diagnostic.Create(
        new DiagnosticDescriptor(
            "BG0001",
            "Class must be partial",
            "The class '{0}' must be declared as partial",
            "BuilderGenerator",
            DiagnosticSeverity.Error,
            true),
        classInfo.Location,
        classInfo.ClassName);
    context.ReportDiagnostic(diagnostic);
    return;
}

浣跨敤绀轰緥

csharp
[GenerateBuilder]
public partial class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

// 浣跨敤鐢熸垚鐨?Builder
var person = Person.CreateBuilder()
    .WithName("寮犱笁")
    .WithAge(30)
    .WithEmail("zhangsan@example.com")
    .Build();

瀛﹀埌鐨勭煡璇嗙偣

  • 宓屽绫荤敓鎴愭妧鏈?
  • 娴佺晠鎺ュ彛锛團luent Interface锛夎璁?
  • 浣跨敤 StringBuilder 鐢熸垚浠g爜
  • 瀹屽叏闄愬畾绫诲瀷鍚嶇О鐨勪娇鐢?
  • 璇婃柇鎶ュ憡鐨勬椂鏈哄拰鏂规硶

鎵╁睍缁冧範

  1. 娣诲姞楠岃瘉锛氬湪 Build() 鏂规硶涓坊鍔犲睘鎬ч獙璇?
  2. 鏀寔榛樿鍊硷細鍏佽閫氳繃鐗规€у弬鏁版寚瀹氬睘鎬х殑榛樿鍊?
  3. 鐢熸垚 With 鏂规硶锛氫负涓嶅彲鍙樺璞$敓鎴?With 鏂规硶
  4. 鏀寔闆嗗悎锛氫负闆嗗悎灞炴€х敓鎴?Add 鏂规硶

鐩稿叧璧勬簮


瀹屾暣椤圭洰缁撴瀯

鐩綍缁撴瀯

05-BuilderGenerator/
鈹溾攢鈹€ BuilderGenerator.slnx
鈹溾攢鈹€ BuilderGenerator.Generator/
鈹?  鈹溾攢鈹€ BuilderGenerator.Generator.csproj
鈹?  鈹溾攢鈹€ BuilderGenerator.cs
鈹?  鈹溾攢鈹€ Attributes/
鈹?  鈹?  鈹溾攢鈹€ GenerateBuilderAttribute.cs
鈹?  鈹?  鈹溾攢鈹€ BuilderPropertyAttribute.cs
鈹?  鈹?  鈹斺攢鈹€ BuilderValidationAttribute.cs
鈹?  鈹斺攢鈹€ Models/
鈹?      鈹溾攢鈹€ ClassInfo.cs
鈹?      鈹斺攢鈹€ PropertyInfo.cs
鈹斺攢鈹€ BuilderGenerator.Consumer/
    鈹溾攢鈹€ BuilderGenerator.Consumer.csproj
    鈹溾攢鈹€ Program.cs
    鈹斺攢鈹€ Models/
        鈹溾攢鈹€ Person.cs
        鈹溾攢鈹€ Product.cs
        鈹溾攢鈹€ Order.cs
        鈹斺攢鈹€ Configuration.cs

椤圭洰閰嶇疆

BuilderGenerator.Generator.csproj:

xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <LangVersion>latest</LangVersion>
    <Nullable>enable</Nullable>
    <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
  </ItemGroup>

</Project>

鐢熸垚娴佺▼鍥?


鐢熸垚鍣ㄥ疄鐜拌瑙?

瀹屾暣鐢熸垚鍣ㄤ唬鐮?

csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Immutable;
using System.Linq;
using System.Text;

namespace BuilderGenerator.Generator
{
    /// <summary>
    /// 涓哄甫鏈?[GenerateBuilder] 鐗规€х殑绫荤敓鎴?Builder 妯″紡浠g爜
    /// </summary>
    [Generator]
    public class BuilderGenerator : IIncrementalGenerator
    {
        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            // 1. 鏌ユ壘甯︽湁 GenerateBuilder 鐗规€х殑绫?
            var classDeclarations = context.SyntaxProvider
                .CreateSyntaxProvider(
                    // 蹇€熻娉曡繃婊?
                    predicate: static (node, _) => IsCandidateClass(node),
                    
                    // 璇箟鍒嗘瀽鍜屾暟鎹彁鍙?
                    transform: static (ctx, _) => GetClassInfo(ctx)
                )
                .Where(static info => info != null);

            // 2. 鐢熸垚 Builder 浠g爜
            context.RegisterSourceOutput(
                classDeclarations,
                static (spc, classInfo) => GenerateBuilderCode(spc, classInfo!)
            );
        }

        /// <summary>
        /// 蹇€熸鏌ワ細鏄惁鏄€欓€夌被
        /// </summary>
        private static bool IsCandidateClass(SyntaxNode node)
        {
            if (node is not ClassDeclarationSyntax classDecl)
                return false;

            if (classDecl.AttributeLists.Count == 0)
                return false;

            if (!classDecl.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
                return false;

            return true;
        }

        /// <summary>
        /// 鎻愬彇绫讳俊鎭?
        /// </summary>
        private static ClassInfo? GetClassInfo(GeneratorSyntaxContext context)
        {
            var classDecl = (ClassDeclarationSyntax)context.Node;
            var symbol = context.SemanticModel.GetDeclaredSymbol(classDecl);

            if (symbol == null)
                return null;

            // 妫€鏌ユ槸鍚︽湁 GenerateBuilder 鐗规€?
            var attribute = symbol.GetAttributes()
                .FirstOrDefault(a => a.AttributeClass?.Name == "GenerateBuilderAttribute");

            if (attribute == null)
                return null;

            // 鑾峰彇鐗规€у弬鏁?
            var generateValidation = GetAttributeValue<bool>(attribute, "GenerateValidation", false);
            var builderClassName = GetAttributeValue<string>(attribute, "BuilderClassName", null) 
                ?? $"{symbol.Name}Builder";

            // 鑾峰彇灞炴€т俊鎭?
            var properties = symbol.GetMembers()
                .OfType<IPropertySymbol>()
                .Where(p => p.DeclaredAccessibility == Accessibility.Public && 
                           p.SetMethod != null)
                .Select(p => new PropertyInfo(
                    Name: p.Name,
                    Type: p.Type.ToDisplayString(),
                    IsRequired: HasRequiredAttribute(p),
                    DefaultValue: GetDefaultValue(p)
                ))
                .ToImmutableArray();

            return new ClassInfo(
                Name: symbol.Name,
                Namespace: symbol.ContainingNamespace.ToDisplayString(),
                BuilderClassName: builderClassName,
                Properties: properties,
                GenerateValidation: generateValidation
            );
        }

        /// <summary>
        /// 鐢熸垚 Builder 浠g爜
        /// </summary>
        private static void GenerateBuilderCode(
            SourceProductionContext context,
            ClassInfo classInfo)
        {
            var sb = new StringBuilder();

            // 鏂囦欢澶?
            sb.AppendLine("// <auto-generated/>");
            sb.AppendLine("#nullable enable");
            sb.AppendLine();
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine();

            // 鍛藉悕绌洪棿
            sb.AppendLine($"namespace {classInfo.Namespace}");
            sb.AppendLine("{");

            // 澶栭儴绫伙紙partial锛?
            sb.AppendLine($"    partial class {classInfo.Name}");
            sb.AppendLine("    {");

            // Builder 宓屽绫?
            sb.AppendLine($"        public class {classInfo.BuilderClassName}");
            sb.AppendLine("        {");

            // 绉佹湁瀛楁
            foreach (var prop in classInfo.Properties)
            {
                sb.AppendLine($"            private {prop.Type} _{ToCamelCase(prop.Name)};");
            }
            sb.AppendLine();

            // With 鏂规硶
            foreach (var prop in classInfo.Properties)
            {
                sb.AppendLine($"            public {classInfo.BuilderClassName} With{prop.Name}({prop.Type} value)");
                sb.AppendLine("            {");
                sb.AppendLine($"                _{ToCamelCase(prop.Name)} = value;");
                sb.AppendLine("                return this;");
                sb.AppendLine("            }");
                sb.AppendLine();
            }

            // Build 鏂规硶
            sb.AppendLine($"            public {classInfo.Name} Build()");
            sb.AppendLine("            {");

            // 楠岃瘉閫昏緫锛堝鏋滈渶瑕侊級
            if (classInfo.GenerateValidation)
            {
                sb.AppendLine("                var errors = new List<string>();");
                sb.AppendLine();

                foreach (var prop in classInfo.Properties.Where(p => p.IsRequired))
                {
                    sb.AppendLine($"                if (_{ToCamelCase(prop.Name)} == null)");
                    sb.AppendLine($"                    errors.Add(\"{prop.Name} is required\");");
                    sb.AppendLine();
                }

                sb.AppendLine("                if (errors.Count > 0)");
                sb.AppendLine("                    throw new InvalidOperationException(");
                sb.AppendLine("                        $\"Validation failed: {string.Join(\", \", errors)}\");");
                sb.AppendLine();
            }

            // 鍒涘缓瀵硅薄
            sb.AppendLine($"                return new {classInfo.Name}");
            sb.AppendLine("                {");

            for (int i = 0; i < classInfo.Properties.Length; i++)
            {
                var prop = classInfo.Properties[i];
                var comma = i < classInfo.Properties.Length - 1 ? "," : "";
                sb.AppendLine($"                    {prop.Name} = _{ToCamelCase(prop.Name)}{comma}");
            }

            sb.AppendLine("                };");
            sb.AppendLine("            }");

            // 鍏抽棴 Builder 绫?
            sb.AppendLine("        }");
            sb.AppendLine();

            // CreateBuilder 闈欐€佹柟娉?
            sb.AppendLine($"        public static {classInfo.BuilderClassName} CreateBuilder()");
            sb.AppendLine("        {");
            sb.AppendLine($"            return new {classInfo.BuilderClassName}();");
            sb.AppendLine("        }");

            // 鍏抽棴澶栭儴绫诲拰鍛藉悕绌洪棿
            sb.AppendLine("    }");
            sb.AppendLine("}");

            // 娣诲姞婧愭枃浠?
            context.AddSource(
                $"{classInfo.Name}.Builder.g.cs",
                sb.ToString()
            );
        }

        // 杈呭姪鏂规硶
        private static string ToCamelCase(string name)
        {
            if (string.IsNullOrEmpty(name))
                return name;

            return char.ToLower(name[0]) + name.Substring(1);
        }

        private static bool HasRequiredAttribute(IPropertySymbol property)
        {
            return property.GetAttributes()
                .Any(a => a.AttributeClass?.Name == "RequiredAttribute" ||
                         a.AttributeClass?.Name == "BuilderRequiredAttribute");
        }

        private static string? GetDefaultValue(IPropertySymbol property)
        {
            var attr = property.GetAttributes()
                .FirstOrDefault(a => a.AttributeClass?.Name == "BuilderDefaultAttribute");

            if (attr == null)
                return null;

            var value = attr.ConstructorArguments.FirstOrDefault().Value;
            return value?.ToString();
        }

        private static T GetAttributeValue<T>(AttributeData attribute, string name, T defaultValue)
        {
            var namedArg = attribute.NamedArguments
                .FirstOrDefault(arg => arg.Key == name);

            if (namedArg.Value.Value is T value)
                return value;

            return defaultValue;
        }
    }

    /// <summary>
    /// 绫讳俊鎭?
    /// </summary>
    internal record ClassInfo(
        string Name,
        string Namespace,
        string BuilderClassName,
        ImmutableArray<PropertyInfo> Properties,
        bool GenerateValidation
    );

    /// <summary>
    /// 灞炴€т俊鎭?
    /// </summary>
    internal record PropertyInfo(
        string Name,
        string Type,
        bool IsRequired,
        string? DefaultValue
    );
}

浠g爜鍒嗘瀽

1. 宓屽绫荤敓鎴?

csharp
// 姝g‘鐨勭缉杩涘眰娆?
sb.AppendLine($"namespace {classInfo.Namespace}");      // 0 绾?
sb.AppendLine("{");
sb.AppendLine($"    partial class {classInfo.Name}");   // 1 绾э紙4 绌烘牸锛?
sb.AppendLine("    {");
sb.AppendLine($"        public class Builder");         // 2 绾э紙8 绌烘牸锛?
sb.AppendLine("        {");
sb.AppendLine($"            private string _name;");    // 3 绾э紙12 绌烘牸锛?

**鍏抽敭鐐?*锛?

  • 姣忕骇缂╄繘 4 涓┖鏍?
  • 宓屽绫诲湪澶栭儴绫诲唴閮?
  • 淇濇寔涓€鑷寸殑缂╄繘椋庢牸

2. 娴佺晠鎺ュ彛瀹炵幇

csharp
public Builder WithName(string value)
{
    _name = value;
    return this;  // 杩斿洖 this 鏀寔閾惧紡璋冪敤
}

**鍏抽敭鐐?*锛?

  • 姣忎釜 With 鏂规硶杩斿洖 this
  • 鏂规硶鍚嶄娇鐢?With 鍓嶇紑
  • 杩斿洖绫诲瀷鏄?Builder 鏈韩

3. 楠岃瘉閫昏緫

csharp
public Person Build()
{
    var errors = new List<string>();
    
    if (_name == null)
        errors.Add("Name is required");
    
    if (errors.Count > 0)
        throw new InvalidOperationException(
            $"Validation failed: {string.Join(", ", errors)}");
    
    return new Person { Name = _name };
}

娴佸紡 API 璁捐

娴佸紡 API 鍘熺悊

鍩烘湰娴佸紡 API

csharp
// 鐢熸垚鐨勪唬鐮?
public class PersonBuilder
{
    private string _name;
    private int _age;
    private string _email;
    
    public PersonBuilder WithName(string value)
    {
        _name = value;
        return this;
    }
    
    public PersonBuilder WithAge(int value)
    {
        _age = value;
        return this;
    }
    
    public PersonBuilder WithEmail(string value)
    {
        _email = value;
        return this;
    }
    
    public Person Build()
    {
        return new Person
        {
            Name = _name,
            Age = _age,
            Email = _email
        };
    }
}

// 浣跨敤
var person = new PersonBuilder()
    .WithName("John")
    .WithAge(30)
    .WithEmail("john@example.com")
    .Build();

娉涘瀷娴佸紡 API

csharp
// 鏀寔娉涘瀷鐨?Builder
public class Builder<T> where T : new()
{
    private readonly Dictionary<string, object> _values = new();
    
    public Builder<T> With(string propertyName, object value)
    {
        _values[propertyName] = value;
        return this;
    }
    
    public T Build()
    {
        var instance = new T();
        foreach (var kvp in _values)
        {
            var property = typeof(T).GetProperty(kvp.Key);
            property?.SetValue(instance, kvp.Value);
        }
        return instance;
    }
}

// 浣跨敤
var person = new Builder<Person>()
    .With("Name", "John")
    .With("Age", 30)
    .Build();

鏉′欢娴佸紡 API

csharp
// 鏀寔鏉′欢璁剧疆鐨?Builder
public class PersonBuilder
{
    private string _name;
    private int _age;
    
    public PersonBuilder WithName(string value)
    {
        _name = value;
        return this;
    }
    
    public PersonBuilder WithAge(int value)
    {
        _age = value;
        return this;
    }
    
    // 鏉′欢璁剧疆
    public PersonBuilder WithNameIf(bool condition, string value)
    {
        if (condition)
            _name = value;
        return this;
    }
    
    // 鏉′欢璁剧疆锛堜娇鐢ㄥ嚱鏁帮級
    public PersonBuilder WithAgeIf(Func<bool> condition, int value)
    {
        if (condition())
            _age = value;
        return this;
    }
    
    public Person Build()
    {
        return new Person { Name = _name, Age = _age };
    }
}

// 浣跨敤
var person = new PersonBuilder()
    .WithName("John")
    .WithAgeIf(isAdult, 30)  // 鍙湪 isAdult 涓?true 鏃惰缃?
    .Build();

闆嗗悎娴佸紡 API

csharp
// 鏀寔闆嗗悎鐨?Builder
public class OrderBuilder
{
    private int _id;
    private readonly List<string> _items = new();
    
    public OrderBuilder WithId(int value)
    {
        _id = value;
        return this;
    }
    
    // 娣诲姞鍗曚釜椤?
    public OrderBuilder AddItem(string item)
    {
        _items.Add(item);
        return this;
    }
    
    // 娣诲姞澶氫釜椤?
    public OrderBuilder AddItems(params string[] items)
    {
        _items.AddRange(items);
        return this;
    }
    
    // 娣诲姞闆嗗悎
    public OrderBuilder AddItems(IEnumerable<string> items)
    {
        _items.AddRange(items);
        return this;
    }
    
    public Order Build()
    {
        return new Order
        {
            Id = _id,
            Items = _items.ToList()
        };
    }
}

// 浣跨敤
var order = new OrderBuilder()
    .WithId(1)
    .AddItem("Item1")
    .AddItem("Item2")
    .AddItems("Item3", "Item4", "Item5")
    .Build();

楂樼骇鍔熻兘

鍔熻兘 1锛氭敮鎸佷笉鍙彉瀵硅薄

csharp
// 涓嶅彲鍙樺璞?
public class ImmutablePerson
{
    public string Name { get; }
    public int Age { get; }
    
    // 绉佹湁鏋勯€犲嚱鏁?
    private ImmutablePerson(string name, int age)
    {
        Name = name;
        Age = age;
    }
    
    // Builder 绫?
    public class Builder
    {
        private string _name;
        private int _age;
        
        public Builder WithName(string value)
        {
            _name = value;
            return this;
        }
        
        public Builder WithAge(int value)
        {
            _age = value;
            return this;
        }
        
        public ImmutablePerson Build()
        {
            return new ImmutablePerson(_name, _age);
        }
    }
    
    public static Builder CreateBuilder() => new Builder();
}

// 浣跨敤
var person = ImmutablePerson.CreateBuilder()
    .WithName("John")
    .WithAge(30)
    .Build();

// person.Name = "Jane";  // 缂栬瘧閿欒锛氬睘鎬ф槸鍙鐨?

鍔熻兘 2锛氭敮鎸侀獙璇?

csharp
[GenerateBuilder(GenerateValidation = true)]
public partial class Person
{
    [Required]
    public string Name { get; set; }
    
    [Range(0, 150)]
    public int Age { get; set; }
    
    [EmailAddress]
    public string Email { get; set; }
}

// 鐢熸垚鐨?Build 鏂规硶
public Person Build()
{
    var errors = new List<string>();
    
    // 楠岃瘉 Name
    if (string.IsNullOrWhiteSpace(_name))
        errors.Add("Name is required");
    
    // 楠岃瘉 Age
    if (_age < 0 || _age > 150)
        errors.Add("Age must be between 0 and 150");
    
    // 楠岃瘉 Email
    if (!IsValidEmail(_email))
        errors.Add("Email is not valid");
    
    if (errors.Count > 0)
        throw new ValidationException(string.Join(", ", errors));
    
    return new Person
    {
        Name = _name,
        Age = _age,
        Email = _email
    };
}

鍔熻兘 3锛氭敮鎸侀粯璁ゅ€?

csharp
[GenerateBuilder]
public partial class Configuration
{
    [BuilderDefault("localhost")]
    public string Host { get; set; }
    
    [BuilderDefault(8080)]
    public int Port { get; set; }
    
    [BuilderDefault(true)]
    public bool EnableLogging { get; set; }
}

// 鐢熸垚鐨?Builder
public class ConfigurationBuilder
{
    private string _host = "localhost";  // 榛樿鍊?
    private int _port = 8080;            // 榛樿鍊?
    private bool _enableLogging = true;  // 榛樿鍊?
    
    public ConfigurationBuilder WithHost(string value)
    {
        _host = value;
        return this;
    }
    
    // ... 鍏朵粬鏂规硶
    
    public Configuration Build()
    {
        return new Configuration
        {
            Host = _host,
            Port = _port,
            EnableLogging = _enableLogging
        };
    }
}

// 浣跨敤锛堝彧璁剧疆闇€瑕佹敼鍙樼殑鍊硷級
var config = Configuration.CreateBuilder()
    .WithPort(9000)  // 鍙敼鍙樼鍙?
    .Build();
// Host = "localhost", Port = 9000, EnableLogging = true

鍔熻兘 4锛氭敮鎸佺户鎵?

csharp
// 鍩虹被
public class BaseEntity
{
    public int Id { get; set; }
    public DateTime CreatedAt { get; set; }
}

// 娲剧敓绫?
[GenerateBuilder(IncludeBaseProperties = true)]
public partial class Product : BaseEntity
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

// 鐢熸垚鐨?Builder 鍖呭惈鍩虹被灞炴€?
public class ProductBuilder
{
    // 鍩虹被灞炴€?
    private int _id;
    private DateTime _createdAt;
    
    // 娲剧敓绫诲睘鎬?
    private string _name;
    private decimal _price;
    
    public ProductBuilder WithId(int value)
    {
        _id = value;
        return this;
    }
    
    public ProductBuilder WithCreatedAt(DateTime value)
    {
        _createdAt = value;
        return this;
    }
    
    public ProductBuilder WithName(string value)
    {
        _name = value;
        return this;
    }
    
    public ProductBuilder WithPrice(decimal value)
    {
        _price = value;
        return this;
    }
    
    public Product Build()
    {
        return new Product
        {
            Id = _id,
            CreatedAt = _createdAt,
            Name = _name,
            Price = _price
        };
    }
}

鍔熻兘 5锛氭敮鎸佸鍒舵瀯閫?

csharp
// 鏀寔浠庣幇鏈夊璞″垱寤?Builder
public class PersonBuilder
{
    private string _name;
    private int _age;
    
    // 榛樿鏋勯€犲嚱鏁?
    public PersonBuilder()
    {
    }
    
    // 浠庣幇鏈夊璞″垱寤?
    public PersonBuilder(Person person)
    {
        _name = person.Name;
        _age = person.Age;
    }
    
    public PersonBuilder WithName(string value)
    {
        _name = value;
        return this;
    }
    
    public PersonBuilder WithAge(int value)
    {
        _age = value;
        return this;
    }
    
    public Person Build()
    {
        return new Person { Name = _name, Age = _age };
    }
}

// 鍦?Person 绫讳腑娣诲姞鏂规硶
public partial class Person
{
    public static PersonBuilder CreateBuilder() => new PersonBuilder();
    
    public PersonBuilder ToBuilder() => new PersonBuilder(this);
}

// 浣跨敤
var person1 = Person.CreateBuilder()
    .WithName("John")
    .WithAge(30)
    .Build();

// 鍩轰簬鐜版湁瀵硅薄鍒涘缓鏂板璞?
var person2 = person1.ToBuilder()
    .WithAge(31)  // 鍙敼鍙樺勾榫?
    .Build();
// person2: Name = "John", Age = 31

鐪熷疄搴旂敤鍦烘櫙

鍦烘櫙 1锛氶厤缃璞℃瀯寤?

**闇€姹?*锛氭瀯寤哄鏉傜殑閰嶇疆瀵硅薄锛屾湁寰堝鍙€夊弬鏁般€?

csharp
[GenerateBuilder]
public partial class DatabaseConfiguration

基于 MIT 许可发布