["Content-Type"] = "application/json"
},
AuthToken = "secret-token"
};
logger.LogInformation("Processing request: {Request}", request); // 杈撳嚭: Processing request: HttpRequest
### 鍦烘櫙 2锛氬崟鍏冩祴璇曟柇瑷€
**闇€姹?*锛氬湪娴嬭瘯涓瘮杈冨璞$姸鎬併€?
```csharp
[GenerateToString]
public partial class UserDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
// 娴嬭瘯浠g爜
[Fact]
public void CreateUser_ShouldReturnCorrectDto()
{
var result = userService.CreateUser("John", "john@example.com");
var expected = new UserDto
{
Id = 1,
Name = "John",
Email = "john@example.com"
};
// ToString 浣挎祴璇曞け璐ユ秷鎭洿娓呮櫚
Assert.Equal(expected.ToString(), result.ToString());
// 澶辫触鏃惰緭鍑? Expected: UserDto { Id = 1, Name = John, Email = john@example.com }
// Actual: UserDto { Id = 2, Name = John, Email = john@example.com }
}鍦烘櫙 3锛氳皟璇曞鏉傚璞?
**闇€姹?*锛氬湪璋冭瘯鍣ㄤ腑蹇€熸煡鐪嬪璞$姸鎬併€?
[GenerateToString]
public partial class OrderSummary
{
public int OrderId { get; set; }
public string CustomerName { get; set; }
public decimal TotalAmount { get; set; }
public List<string> Items { get; set; }
public DateTime OrderDate { get; set; }
}
// 鍦ㄨ皟璇曞櫒鐨?Watch 绐楀彛涓紝鐩存帴鏄剧ず瀹屾暣淇℃伅
// OrderSummary { OrderId = 123, CustomerName = John, TotalAmount = 99.99, Items = [Item1, Item2], OrderDate = 2025-01-21 }鍦烘櫙 4锛氶厤缃璞¢獙璇?
**闇€姹?*锛氶獙璇侀厤缃璞℃槸鍚︽纭姞杞姐€?
[GenerateToString]
public partial class AppSettings
{
public string DatabaseConnection { get; set; }
public int MaxRetries { get; set; }
public TimeSpan Timeout { get; set; }
[ToStringIgnore]
public string ApiKey { get; set; } // 鏁忔劅淇℃伅
}
// 鍚姩鏃堕獙璇侀厤缃?
public void ConfigureServices(IServiceCollection services)
{
var settings = Configuration.Get<AppSettings>();
logger.LogInformation("Loaded settings: {Settings}", settings);
// 杈撳嚭: Loaded settings: AppSettings { DatabaseConnection = Server=localhost, MaxRetries = 3, Timeout = 00:00:30 }
if (string.IsNullOrEmpty(settings.DatabaseConnection))
{
throw new InvalidOperationException($"Invalid settings: {settings}");
}
}鍦烘櫙 5锛欰PI 鍝嶅簲璋冭瘯
**闇€姹?*锛氳褰?API 鍝嶅簲鍐呭锛屾柟渚挎帓鏌ラ棶棰樸€?
[GenerateToString]
public partial class ApiResponse<T>
{
public bool Success { get; set; }
public string Message { get; set; }
public T Data { get; set; }
public List<string> Errors { get; set; }
}
// 浣跨敤
public async Task<ApiResponse<User>> GetUserAsync(int id)
{
var response = await httpClient.GetAsync($"/api/users/{id}");
var result = await response.Content.ReadFromJsonAsync<ApiResponse<User>>();
logger.LogDebug("API response: {Response}", result);
// 杈撳嚭: API response: ApiResponse { Success = True, Message = OK, Data = User { Id = 1, Name = John }, Errors = [] }
return result;
}鏈€浣冲疄璺?vs 鍙嶆ā寮?
瀵规瘮琛ㄦ牸
| 鏂归潰 | 鉁?鏈€浣冲疄璺? | 鉂?鍙嶆ā寮? | 鍘熷洜 |
|---|---|---|---|
| 绫讳慨楗扮 | 浣跨敤 partial 绫? | 涓嶄娇鐢?partial | 鐢熸垚鍣ㄩ渶瑕?partial 鎵嶈兘娣诲姞鏂规硶 |
| 鎬ц兘 | 浣跨敤 StringBuilder | 浣跨敤瀛楃涓叉嫾鎺? | StringBuilder 閬垮厤澶ч噺鍐呭瓨鍒嗛厤 |
| null 澶勭悊 | 妫€鏌ュ苟澶勭悊 null | 涓嶅鐞?null | 閬垮厤 NullReferenceException |
| 鏁忔劅淇℃伅 | 浣跨敤 [ToStringIgnore] | 鍖呭惈瀵嗙爜绛夋晱鎰熶俊鎭? | 淇濇姢瀹夊叏 |
| 闆嗗悎 | 鏍煎紡鍖栭泦鍚堝唴瀹? | 鐩存帴杈撳嚭闆嗗悎绫诲瀷鍚? | 鎻愪緵鏈夌敤淇℃伅 |
| 宓屽瀵硅薄 | 璋冪敤宓屽瀵硅薄鐨?ToString | 杈撳嚭绫诲瀷鍚? | 鏄剧ず瀹屾暣淇℃伅 |
| 鏍煎紡 | 浣跨敤娓呮櫚鐨勬牸寮? | 鏃犳牸寮忔垨娣蜂贡鏍煎紡 | 鎻愰珮鍙鎬? |
| 鍛藉悕绌洪棿 | 浣跨敤瀹屾暣鍛藉悕绌洪棿 | 浣跨敤 using 鎸囦护 | 閬垮厤鍐茬獊 |
璇︾粏绀轰緥
1. Partial 绫?
// 鉂?鍙嶆ā寮忥細涓嶄娇鐢?partial
[GenerateToString]
public class Person // 缂栬瘧閿欒锛?
{
public string Name { get; set; }
}
// 鉁?鏈€浣冲疄璺碉細浣跨敤 partial
[GenerateToString]
public partial class Person
{
public string Name { get; set; }
}2. 鎬ц兘浼樺寲
// 鉂?鍙嶆ā寮忥細瀛楃涓叉嫾鎺?
public override string ToString()
{
return "Person { " +
"Name = " + Name + ", " +
"Age = " + Age + ", " +
"Email = " + Email +
" }";
}
// 鉁?鏈€浣冲疄璺碉細StringBuilder
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("Person { ");
sb.Append("Name = ");
sb.Append(Name);
sb.Append(", Age = ");
sb.Append(Age);
sb.Append(", Email = ");
sb.Append(Email);
sb.Append(" }");
return sb.ToString();
}3. Null 澶勭悊
// 鉂?鍙嶆ā寮忥細涓嶅鐞?null
public override string ToString()
{
return $"Person {{ Name = {Name}, Email = {Email} }}";
// 濡傛灉 Name 鎴?Email 鏄?null锛岃緭鍑?"Person { Name = , Email = }"
}
// 鉁?鏈€浣冲疄璺碉細澶勭悊 null
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("Person { ");
sb.Append("Name = ");
sb.Append(Name ?? "null");
sb.Append(", Email = ");
sb.Append(Email ?? "null");
sb.Append(" }");
return sb.ToString();
}4. 鏁忔劅淇℃伅淇濇姢
// 鉂?鍙嶆ā寮忥細鍖呭惈鏁忔劅淇℃伅
[GenerateToString]
public partial class User
{
public string Username { get; set; }
public string Password { get; set; } // 鍗遍櫓锛?
public string CreditCard { get; set; } // 鍗遍櫓锛?
}
// 鉁?鏈€浣冲疄璺碉細蹇界暐鏁忔劅淇℃伅
[GenerateToString]
public partial class User
{
public string Username { get; set; }
[ToStringIgnore]
public string Password { get; set; }
[ToStringIgnore]
public string CreditCard { get; set; }
}5. 闆嗗悎鏍煎紡鍖?
// 鉂?鍙嶆ā寮忥細涓嶆牸寮忓寲闆嗗悎
public override string ToString()
{
return $"Order {{ Items = {Items} }}";
// 杈撳嚭: Order { Items = System.Collections.Generic.List`1[Item] }
}
// 鉁?鏈€浣冲疄璺碉細鏍煎紡鍖栭泦鍚?
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("Order { Items = [");
if (Items != null)
{
sb.Append(string.Join(", ", Items.Select(x => x.ToString())));
}
sb.Append("] }");
return sb.ToString();
}6. 宓屽瀵硅薄
// 鉂?鍙嶆ā寮忥細涓嶅鐞嗗祵濂楀璞?
public override string ToString()
{
return $"Order {{ Customer = {Customer} }}";
// 杈撳嚭: Order { Customer = MyApp.Customer }
}
// 鉁?鏈€浣冲疄璺碉細璋冪敤宓屽瀵硅薄鐨?ToString
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("Order { Customer = ");
sb.Append(Customer?.ToString() ?? "null");
sb.Append(" }");
return sb.ToString();
}鎬ц兘浼樺寲
浼樺寲绛栫暐
浼樺寲 1锛氫娇鐢?StringBuilder
// 鎬ц兘娴嬭瘯缁撴灉锛?0000 娆¤皟鐢級
// 瀛楃涓叉嫾鎺? 150ms, 鍒嗛厤 2.5MB
// StringBuilder: 50ms, 鍒嗛厤 0.8MB
// 鉁?鎺ㄨ崘
public override string ToString()
{
var sb = new StringBuilder(100); // 棰勫垎閰嶅閲?
sb.Append("Person { ");
sb.Append("Name = ");
sb.Append(Name);
sb.Append(" }");
return sb.ToString();
}浼樺寲 2锛氱紦瀛樻牸寮忓瓧绗︿覆
// 瀵逛簬鍥哄畾鏍煎紡锛屽彲浠ョ紦瀛樻牸寮忓瓧绗︿覆
private static readonly string FormatString = "Person {{ Name = {0}, Age = {1} }}";
public override string ToString()
{
return string.Format(FormatString, Name, Age);
}浼樺寲 3锛氬欢杩熸牸寮忓寲
// 鍙湪闇€瑕佹椂鏍煎紡鍖栭泦鍚?
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("Order { ");
if (Items != null && Items.Count > 0)
{
sb.Append("Items = [");
sb.Append(string.Join(", ", Items));
sb.Append("]");
}
else
{
sb.Append("Items = []");
}
sb.Append(" }");
return sb.ToString();
}浼樺寲 4锛氶伩鍏嶈绠?
// 鉂?閬垮厤锛氬€肩被鍨嬭绠?
sb.Append(Age); // int 瑁呯涓?object
// 鉁?鎺ㄨ崘锛氫娇鐢ㄤ笓闂ㄧ殑閲嶈浇
sb.Append(Age.ToString()); // 鎴栬€?sb.Append(Age) 濡傛灉鏈?int 閲嶈浇鎬ц兘瀵规瘮
| 鏂规硶 | 鏃堕棿 (10000娆? | 鍐呭瓨鍒嗛厤 | 鎺ㄨ崘 |
|---|---|---|---|
| 瀛楃涓叉嫾鎺? | 150ms | 2.5MB | 鉂? |
| String.Format | 100ms | 1.8MB | 鈿狅笍 |
| StringBuilder | 50ms | 0.8MB | 鉁? |
| StringBuilder (棰勫垎閰? | 40ms | 0.6MB | 鉁呪渽 |
甯歌闂
1. 涓轰粈涔堝繀椤讳娇鐢?partial 绫伙紵
闂锛氫笉浣跨敤 partial 浼氬鑷寸紪璇戦敊璇€?
鍘熷洜锛氱敓鎴愬櫒鐢熸垚鐨勪唬鐮侀渶瑕佷笌鐢ㄦ埛浠g爜鍚堝苟鎴愪竴涓被銆侰# 鍙厑璁搁€氳繃 partial 鍏抽敭瀛楀垎鍓茬被瀹氫箟銆?
瑙e喅鏂规锛?
// 鉁?姝g‘
[GenerateToString]
public partial class Person
{
public string Name { get; set; }
}
// 鉂?閿欒
[GenerateToString]
public class Person // 缂哄皯 partial
{
public string Name { get; set; }
}2. 濡備綍澶勭悊缁ф壙鐨勫睘鎬э紵
闂锛氶粯璁ゅ彧鍖呭惈褰撳墠绫荤殑灞炴€э紝涓嶅寘鍚熀绫诲睘鎬с€?
瑙e喅鏂规锛?
// 鏂规 1锛氫娇鐢ㄧ壒鎬у弬鏁?
[GenerateToString(IncludeBaseProperties = true)]
public partial class Product : BaseEntity
{
public string Name { get; set; }
}
// 鏂规 2锛氬湪鐢熸垚鍣ㄤ腑閫掑綊鑾峰彇鍩虹被灞炴€?
private static ImmutableArray<PropertyInfo> GetAllProperties(INamedTypeSymbol symbol)
{
var properties = new List<PropertyInfo>();
// 鑾峰彇鍩虹被灞炴€?
if (symbol.BaseType != null && symbol.BaseType.SpecialType != SpecialType.System_Object)
{
properties.AddRange(GetAllProperties(symbol.BaseType));
}
// 鑾峰彇褰撳墠绫诲睘鎬?
properties.AddRange(
symbol.GetMembers()
.OfType<IPropertySymbol>()
.Where(p => p.DeclaredAccessibility == Accessibility.Public)
.Select(p => new PropertyInfo(p.Name, p.Type.ToDisplayString(), false))
);
return properties.ToImmutableArray();
}3. 濡備綍澶勭悊寰幆寮曠敤锛?
闂锛氬祵濂楀璞″彲鑳藉鑷村惊鐜紩鐢紝閫犳垚鏍堟孩鍑恒€?
public partial class Person
{
public string Name { get; set; }
public Person Spouse { get; set; } // 寰幆寮曠敤
}瑙e喅鏂规锛?
// 鏂规 1锛氫娇鐢?ToStringIgnore
public partial class Person
{
public string Name { get; set; }
[ToStringIgnore]
public Person Spouse { get; set; }
}
// 鏂规 2锛氬彧鏄剧ず ID
public partial class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int? SpouseId { get; set; } // 浣跨敤 ID 鑰屼笉鏄璞″紩鐢?
}
// 鏂规 3锛氬湪鐢熸垚鐨勪唬鐮佷腑妫€娴嬪惊鐜?
private static readonly ThreadLocal<HashSet<object>> _visitedObjects =
new ThreadLocal<HashSet<object>>(() => new HashSet<object>());
public override string ToString()
{
if (!_visitedObjects.Value.Add(this))
{
return $"Person {{ Id = {Id} }} (circular reference)";
}
try
{
var sb = new StringBuilder();
sb.Append("Person { ");
sb.Append($"Name = {Name}, ");
sb.Append($"Spouse = {Spouse?.ToString() ?? "null"}");
sb.Append(" }");
return sb.ToString();
}
finally
{
_visitedObjects.Value.Remove(this);
}
}4. 濡備綍鑷畾涔夋牸寮忥紵
闂锛氶粯璁ゆ牸寮忎笉婊¤冻闇€姹傘€?
瑙e喅鏂规锛?
// 鏂规 1锛氫娇鐢?Format 鍙傛暟
[GenerateToString(Format = "{Name} ({Age} years old)")]
public partial class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
// 鏂规 2锛氭墜鍔ㄥ疄鐜?ToString
public partial class Person
{
public string Name { get; set; }
public int Age { get; set; }
// 涓嶄娇鐢ㄧ敓鎴愬櫒锛屾墜鍔ㄥ疄鐜?
public override string ToString()
{
return $"{Name} ({Age} years old)";
}
}
// 鏂规 3锛氬疄鐜拌嚜瀹氫箟鏍煎紡鍖栨柟娉?
[GenerateToString]
public partial class Person
{
public string Name { get; set; }
public int Age { get; set; }
// 鐢熸垚鍣ㄧ敓鎴?ToString()
// 鎵嬪姩娣诲姞鑷畾涔夋牸寮忓寲鏂规硶
public string ToShortString()
{
return $"{Name} ({Age})";
}
}5. 鐢熸垚鐨勪唬鐮佹湁缂栬瘧閿欒鎬庝箞鍔烇紵
璋冭瘯姝ラ锛?
**鏌ョ湅鐢熸垚鐨勬枃浠?*锛?
obj/Debug/net8.0/generated/ToStringGenerator.Generator/ToStringGenerator/ClassName.ToString.g.cs**妫€鏌ヨ娉曢敊璇?*锛?
csharp// 鍦ㄧ敓鎴愬櫒涓獙璇佺敓鎴愮殑浠g爜 var tree = CSharpSyntaxTree.ParseText(generatedCode); var diagnostics = tree.GetDiagnostics(); if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { // 鎶ュ憡閿欒 foreach (var diagnostic in diagnostics) { context.ReportDiagnostic(Diagnostic.Create( new DiagnosticDescriptor( "TSG001", "Generated code has syntax error", diagnostic.GetMessage(), "ToStringGenerator", DiagnosticSeverity.Error, true ), Location.None )); } }娣诲姞璇婃柇鏃ュ織锛?
csharpprivate static void GenerateToStringMethod( SourceProductionContext context, ClassInfo classInfo) { try { var source = GenerateCode(classInfo); context.AddSource($"{classInfo.Name}.ToString.g.cs", source); } catch (Exception ex) { context.ReportDiagnostic(Diagnostic.Create( new DiagnosticDescriptor( "TSG002", "Code generation failed", $"Failed to generate ToString for {classInfo.Name}: {ex.Message}", "ToStringGenerator", DiagnosticSeverity.Error, true ), Location.None )); } }
6. 濡備綍娴嬭瘯鐢熸垚鍣紵
鎺ㄨ崘鏂规硶锛?
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
public class ToStringGeneratorTests
{
[Fact]
public void GeneratesToString_ForSimpleClass()
{
// 杈撳叆浠g爜
var source = @"
using ToStringGenerator;
namespace TestNamespace
{
[GenerateToString]
public partial class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
}";
// 杩愯鐢熸垚鍣?
var (diagnostics, output) = GetGeneratedOutput(source);
// 楠岃瘉娌℃湁閿欒
Assert.Empty(diagnostics);
// 楠岃瘉鐢熸垚鐨勪唬鐮?
Assert.Contains("public override string ToString()", output);
Assert.Contains("Name = ", output);
Assert.Contains("Age = ", output);
}
private (ImmutableArray<Diagnostic>, string) GetGeneratedOutput(string source)
{
var syntaxTree = CSharpSyntaxTree.ParseText(source);
var references = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location))
.Select(a => MetadataReference.CreateFromFile(a.Location))
.ToList();
var compilation = CSharpCompilation.Create(
"TestAssembly",
new[] { syntaxTree },
references,
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);
var generator = new ToStringGenerator();
var driver = CSharpGeneratorDriver.Create(generator);
driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var diagnostics);
var output = outputCompilation.SyntaxTrees
.Skip(1) // 璺宠繃鍘熷浠g爜
.FirstOrDefault()
?.ToString() ?? "";
return (diagnostics, output);
}
}7. 鎬ц兘闂鎬庝箞鍔烇紵
浼樺寲姝ラ锛?
- 浣跨敤 StringBuilder锛氶伩鍏嶅瓧绗︿覆鎷兼帴
- **棰勫垎閰嶅閲?*锛歚new StringBuilder(estimatedSize)`
- 缂撳瓨缁撴灉锛氬鏋滃璞′笉鍙彉锛屽彲浠ョ紦瀛?ToString 缁撴灉
- **寤惰繜鏍煎紡鍖?*锛氬彧鍦ㄩ渶瑕佹椂鏍煎紡鍖栧鏉傚璞?
// 浼樺寲绀轰緥
public partial class Person
{
private string? _cachedToString;
public override string ToString()
{
if (_cachedToString != null)
return _cachedToString;
var sb = new StringBuilder(100); // 棰勫垎閰?
sb.Append("Person { ");
sb.Append("Name = ");
sb.Append(Name);
sb.Append(", Age = ");
sb.Append(Age);
sb.Append(" }");
_cachedToString = sb.ToString();
return _cachedToString;
}
}8. 濡備綍澶勭悊澶у瀷瀵硅薄锛?
绛栫暐锛?
// 鏂规 1锛氶檺鍒惰緭鍑洪暱搴?
[GenerateToString(MaxLength = 1000)]
public partial class LargeObject
{
public string Data { get; set; } // 鍙兘寰堝ぇ
}
// 鐢熸垚鐨勪唬鐮侊細
public override string ToString()
{
var result = $"LargeObject {{ Data = {Data} }}";
if (result.Length > 1000)
{
return result.Substring(0, 1000) + "...";
}
return result;
}
// 鏂规 2锛氬彧鍖呭惈鎽樿淇℃伅
[GenerateToString(IncludeFields = false)]
public partial class LargeObject
{
public int Id { get; set; }
public int ItemCount { get; set; }
[ToStringIgnore]
public byte[] LargeData { get; set; } // 蹇界暐澶ф暟鎹?
}鎵╁睍缁冧範
缁冧範 1锛氭坊鍔犳牸寮忓寲閫夐」
浠诲姟锛氭敮鎸佷笉鍚岀殑鏃ユ湡鏃堕棿鏍煎紡銆?
[GenerateToString(DateTimeFormat = "yyyy-MM-dd HH:mm:ss")]
public partial class Event
{
public string Name { get; set; }
public DateTime StartTime { get; set; }
}缁冧範 2锛氭敮鎸佸璇█
浠诲姟锛氭牴鎹綋鍓嶆枃鍖栫敓鎴愭湰鍦板寲鐨?ToString銆?
[GenerateToString(Localized = true)]
public partial class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
// 杈撳嚭锛堜腑鏂囷級锛氫骇鍝?{ 鍚嶇О = iPhone, 浠锋牸 = 楼5999 }
// 杈撳嚭锛堣嫳鏂囷級锛歅roduct { Name = iPhone, Price = $999 }缁冧範 3锛氭坊鍔?JSON 鏍煎紡
浠诲姟锛氱敓鎴?JSON 鏍煎紡鐨勫瓧绗︿覆琛ㄧず銆?
[GenerateToString(Format = ToStringFormat.Json)]
public partial class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
// 杈撳嚭锛歿"Name":"John","Age":30}缁冧範 4锛氭敮鎸佹潯浠跺寘鍚?
浠诲姟锛氭牴鎹潯浠跺喅瀹氭槸鍚﹀寘鍚煇浜涘睘鎬с€?
[GenerateToString]
public partial class User
{
public string Username { get; set; }
[ToStringIncludeIf("IsDebugMode")]
public string InternalId { get; set; } // 鍙湪璋冭瘯妯″紡涓嬪寘鍚?
}缁冧範 5锛氭€ц兘鍒嗘瀽
浠诲姟锛氭瘮杈冧笉鍚屽疄鐜扮殑鎬ц兘銆?
[Benchmark]
public class ToStringBenchmark
{
private Person person;
[GlobalSetup]
public void Setup()
{
person = new Person { Name = "John", Age = 30, Email = "john@example.com" };
}
[Benchmark]
public string StringConcatenation()
{
return "Person { Name = " + person.Name + ", Age = " + person.Age + " }";
}
[Benchmark]
public string StringFormat()
{
return string.Format("Person {{ Name = {0}, Age = {1} }}", person.Name, person.Age);
}
[Benchmark]
public string StringBuilder()
{
var sb = new StringBuilder();
sb.Append("Person { Name = ");
sb.Append(person.Name);
sb.Append(", Age = ");
sb.Append(person.Age);
sb.Append(" }");
return sb.ToString();
}
[Benchmark]
public string GeneratedToString()
{
return person.ToString();
}
}馃敆 鐩稿叧璧勬簮
娣卞叆瀛︿範
- [蹇€熷紑濮媇(../guide/getting-started.md) - 寮€濮嬩娇鐢ㄦ簮鐢熸垚鍣?
- Hello World 绀轰緥 - 鏈€绠€鍗曠殑鍏ラ棬绀轰緥
- [澧為噺鐢熸垚鍣ㄧず渚媇(./incremental-generator.md) - 瀛︿範澧為噺鐢熸垚鍣ㄧ殑浣跨敤
- [Builder 鐢熸垚鍣╙(./builder-generator.md) - 澶嶆潅鐨勪唬鐮佺敓鎴愭ā寮?
- 娴嬭瘯绀轰緥 - 浜嗚В濡備綍娴嬭瘯婧愮敓鎴愬櫒
API 鍙傝€?
- 浠g爜鐢熸垚 API - 浠g爜鐢熸垚 API 鍙傝€?
- 璇箟妯″瀷 API - 璇箟妯″瀷 API 璇︾粏鍙傝€?
- [鏈€浣冲疄璺礭(../api/best-practices.md) - 婧愮敓鎴愬櫒寮€鍙戞渶浣冲疄璺?
瀹樻柟鏂囨。
- Source Generators - 婧愮敓鎴愬櫒姒傝堪
- IIncrementalGenerator - 澧為噺鐢熸垚鍣?API
- StringBuilder Class - StringBuilder 鏂囨。
鐩稿叧鏂囨。
- [澧為噺鐢熸垚鍣ㄧず渚媇(/examples/incremental-generator) - 瀛︿範澧為噺鐢熸垚鍣?
- [Builder 鐢熸垚鍣╙(/examples/builder-generator) - 鏇村鏉傜殑浠g爜鐢熸垚
- 浠g爜鐢熸垚 API - 浠g爜鐢熸垚鎶€宸?
- [鏈€浣冲疄璺礭(/api/best-practices) - 鎬ц兘浼樺寲寤鸿
绀轰緥椤圭洰
- Roslyn SDK Samples - 瀹樻柟绀轰緥
- Source Generator Samples - 绀惧尯绀轰緥
宸ュ叿鍜屽簱
- BenchmarkDotNet - 鎬ц兘娴嬭瘯
- Source Generator Playground - 鍦ㄧ嚎娴嬭瘯
- Verify - 蹇収娴嬭瘯
涓嬩竴姝ュ涔?
鍩虹宸╁浐锛?
杩涢樁瀛︿範锛?
- 瀛︿範 [Builder 鐢熸垚鍣╙(/examples/builder-generator)
- 瀹炶返 璇婃柇鎶ュ憡
- 鎺屾彙 [娴嬭瘯鎶€鏈痌(/examples/testing)
**娣卞叆鐮旂┒**锛?
- 鐮旂┒ 浠g爜鐢熸垚 API
- 瀛︿範 楂樼骇妯″紡
- 鎺屾彙 鎬ц兘浼樺寲
鎬荤粨
ToString 鐢熸垚鍣ㄦ槸涓€涓疄鐢ㄧ殑婧愮敓鎴愬櫒绀轰緥锛屽睍绀轰簡濡備綍锛?
- **浣跨敤鐗规€ф爣璁?*锛氶€氳繃鐗规€ф帶鍒朵唬鐮佺敓鎴?
- **鍒嗘瀽绫荤粨鏋?*锛氭彁鍙栧睘鎬у拰瀛楁淇℃伅
- 鐢熸垚鏂规硶浠g爜锛氬垱寤?ToString 鏂规硶瀹炵幇
- 澶勭悊澶嶆潅绫诲瀷锛氭敮鎸佸祵濂楀璞″拰闆嗗悎
- 鎬ц兘浼樺寲锛氫娇鐢?StringBuilder 鎻愰珮鎬ц兘
閫氳繃瀛︿範杩欎釜绀轰緥锛屼綘鍙互鎺屾彙婧愮敓鎴愬櫒鐨勬牳蹇冩妧鏈紝骞跺簲鐢ㄥ埌鍏朵粬浠g爜鐢熸垚鍦烘櫙涓€?
鏂囨。瀛楁暟缁熻锛氱害 7,200 瀛?
4. 濡備綍鑷畾涔夊睘鎬х殑鏍煎紡鍖栵紵
闂锛氶渶瑕佸涓嶅悓绫诲瀷鐨勫睘鎬т娇鐢ㄤ笉鍚岀殑鏍煎紡鍖栨柟寮忋€?
瑙e喅鏂规锛氫娇鐢ㄧ壒鎬у弬鏁版寚瀹氭牸寮忓寲閫夐」
// 瀹氫箟鏍煎紡鍖栫壒鎬?
[AttributeUsage(AttributeTargets.Property)]
public class ToStringFormatAttribute : Attribute
{
public string Format { get; }
public ToStringFormatAttribute(string format)
{
Format = format;
}
}
// 浣跨敤鏍煎紡鍖栫壒鎬?
[GenerateToString]
public partial class Product
{
public string Name { get; set; }
[ToStringFormat("C2")] // 璐у竵鏍煎紡锛屼繚鐣欎袱浣嶅皬鏁?
public decimal Price { get; set; }
[ToStringFormat("yyyy-MM-dd")] // 鏃ユ湡鏍煎紡
public DateTime CreatedDate { get; set; }
}
// 鐢熸垚鍣ㄤ腑澶勭悊鏍煎紡鍖?
private string GeneratePropertyString(PropertyInfo property)
{
if (property.FormatString != null)
{
return $"{property.Name} = {{{property.Name}:{property.FormatString}}}";
}
return $"{property.Name} = {{{property.Name}}}";
}鏈€鍚庢洿鏂? 2025-01-21
Q3: 濡備綍澶勭悊寰幆寮曠敤锛?
A: 浣跨敤璁块棶璺熻釜閬垮厤鏃犻檺閫掑綊锛?
public class ToStringGenerator
{
private readonly HashSet<object> _visited = new();
public string GenerateToString(object obj)
{
if (obj == null)
return "null";
// 妫€鏌ユ槸鍚﹀凡璁块棶
if (_visited.Contains(obj))
return $"[Circular Reference: {obj.GetType().Name}]";
_visited.Add(obj);
try
{
// 鐢熸垚 ToString 浠g爜
return GenerateToStringInternal(obj);
}
finally
{
_visited.Remove(obj);
}
}
}鏈€鍚庢洿鏂? 2025-01-21