-
Notifications
You must be signed in to change notification settings - Fork 0
EN 01_faq_and_rationale
🇺🇸 English | 🇯🇵 日本語 | Introduction
This chapter outlines the architectural philosophy behind the zero-allocation v4 generator and answers frequently asked questions regarding API design, code synthesis, and integration with modern .NET features.
Writing DependencyProperty in XAML frameworks such as .NET MAUI, WPF, WinUI, and Avalonia is notoriously verbose. The primary goal of DependencyPropertyGenerator is to eliminate this boilerplate without degrading IDE responsiveness at scale.
To achieve high-throughput, zero-allocation generation, the v4 pipeline relies on the following aggressive architectural shifts:
The generator drops NormalizeWhitespace() and manual indentation entirely. It outputs flat, left-aligned code.
- Performance win: Eliminates thousands of whitespace string allocations on the hot path.
- AI/LLM win: Lightweight models such as Gemini Flash often hallucinate or misalign whitespace when predicting code. Flat output ensures deterministic, stable generation without brittle whitespace matching.
We strictly avoid SyntaxFactory mutations for code synthesis. Whether generating class definitions or resolving dynamic DefaultValueExpression declarations such as converting new() to explicit types, we extract tokens from the parsed AST and stream them straight into a custom SourceWriter.
- Zero Gen2 Allocations: Bypassing AST construction completely prevents Gen2 GC spikes.
Generation logic runs on stack-allocated SourceWriter and ClassScope wrappers, completely bypassing heap allocations for string assembly.
Note
For detailed code specifications on token streaming, SourceWriter / ClassScope implementation conventions, and micro-benchmark metrics comparing AST mutation vs. token streaming, see 05. Code Synthesis and Performance.
To enable "Write Once, Run on Any XAML Platform".
By isolating the data extraction phase into pure DTOs and delegating output to platform-specific strategies, a single [DependencyProperty] attribute can synthesize DependencyProperty.Register for WPF, AvaloniaProperty.Register for Avalonia, and BindableProperty.Create for MAUI. This drastically reduces #if boilerplate for OSS library authors and enterprise teams migrating between UI frameworks.
When Avalonia 12.2 introduces official source generator support, we will evaluate its adoption and community consensus.
While official generators provide platform-native excellence, this library will continue to maintain AvaloniaFrameworkGenerator as long as there is value in a unified, multi-targeted [DependencyProperty] attribute shared across WPF, MAUI, and Avalonia codebases. Deprecation will only be considered if the community fully standardizes on the official generator and multi-target demand diminishes.
Why use class-level attributes instead of field-level attributes like in MVVM Toolkit or C# 13 partial properties?
Class-level attributes provide a unified mental model for declaring both standard Dependency Properties and Attached Properties, which do not map cleanly to backing fields. However, C# 13 partial property support is natively implemented and works seamlessly alongside class-level attributes, utilizing the same underlying AST parsing logic.
No. Formatting generated code is the IDE/formatter's responsibility. It is inefficient to allocate megabytes of whitespace per keystroke on the generator hot path just for intermediate visual formatting.
If you need to read the generated file for debugging, you can use the format document feature in your IDE to instantly indent it. Furthermore, #line directives ensure stack traces and compiler errors map perfectly back to your original source files.
Through convention-based partial methods. If you define partial void CoerceIsActive(ref bool value) or partial bool ValidateIsActive(bool value), the generator detects them and automatically wires up the metadata callbacks. Framework-specific flags like AffectsRender = true or BindsTwoWayByDefault are simply declared via attribute arguments.
The internal synthesis pipeline—AST token extraction, string assembly, and SourceWriter buffering—allocates exactly 0 Bytes. The remaining 2.22 MB represents the unavoidable overhead of Roslyn's API boundaries: Incremental Pipeline caching overhead, GeneratorInitializationContext, and the mandatory final SourceText string allocation when handing the generated code back to the compiler host. Our proprietary generation logic itself remains strictly zero-allocation.
For end-to-end benchmark measurements and reduction ratios, see Section VI. Performance Metrics in 05. Code Synthesis and Performance.
No. The generator outputs standard, static C# code with explicit DependencyProperty.Register calls. There is absolutely zero runtime reflection or Reflection.Emit involved, making the output 100% NativeAOT and Trimming safe. Because it generates static fields and property wrappers at compile-time, it plays perfectly with XAML Hot Reload and Language Server Protocol, functioning exactly like hand-written code.
This wiki is automatically synchronized from spec/ in the repository.
- Introduction
- 01. FAQ & Design Rationale
- 02. Foundation & Domain
- 03. Pipeline Architecture
- 04. Framework Strategies
- 05. Synthesis & Performance
- 06. Complexity Model
- 07. Test Specification
- 08. Diagnostics Reference
- 概要
- 01. 設計思想とFAQ
- 02. 基盤とドメイン
- 03. パイプライン構造
- 04. フレームワーク別生成仕様
- 05. コード生成と最適化
- 06. 計算量モデル
- 07. テスト仕様書
- 08. 診断機能リファレンス