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爜
- 瀹屽叏闄愬畾绫诲瀷鍚嶇О鐨勪娇鐢?
- 璇婃柇鎶ュ憡鐨勬椂鏈哄拰鏂规硶
鎵╁睍缁冧範
- 娣诲姞楠岃瘉锛氬湪
Build()鏂规硶涓坊鍔犲睘鎬ч獙璇? - 鏀寔榛樿鍊硷細鍏佽閫氳繃鐗规€у弬鏁版寚瀹氬睘鎬х殑榛樿鍊?
- 鐢熸垚 With 鏂规硶锛氫负涓嶅彲鍙樺璞$敓鎴?
With鏂规硶 - 鏀寔闆嗗悎锛氫负闆嗗悎灞炴€х敓鎴?
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