# 機能設計書 2-AvaloniaProperty

## 概要

本ドキュメントは、Avaloniaフレームワークの依存関係プロパティの定義と管理を行う中核クラスである`AvaloniaProperty`の機能設計を記述する。`StyledProperty`と`DirectProperty`の基底クラスとして、プロパティの登録、メタデータ管理、変更通知を提供する。

### 本機能の処理概要

`AvaloniaProperty`は、`AvaloniaObject`に設定可能なプロパティを定義するための抽象基底クラスである。プロパティの名前、型、所有者型、継承設定、デフォルト値、バリデーション、コアース（値補正）などのメタデータを管理し、プロパティシステム全体の基盤を形成する。

**業務上の目的・背景**：通常のCLRプロパティでは実現できない、スタイリング、データバインディング、アニメーション、継承といったUIフレームワーク固有の機能をサポートするため、プロパティを専用のシステムで管理する必要がある。`AvaloniaProperty`は、プロパティの定義を型安全に行い、ランタイムでの高速なプロパティアクセスを可能にする。

**機能の利用シーン**：
- カスタムコントロール作成時のプロパティ定義
- 既存プロパティのメタデータオーバーライド
- アタッチドプロパティの定義
- プロパティ変更のグローバル監視

**主要な処理内容**：
1. `Register`メソッドによるStyledPropertyの登録
2. `RegisterAttached`メソッドによるアタッチドプロパティの登録
3. `RegisterDirect`メソッドによるDirectPropertyの登録
4. `GetMetadata`メソッドによる型別メタデータの取得
5. `OverrideMetadata`によるメタデータの上書き
6. `Changed`オブザーバブルによるグローバルな変更監視
7. 演算子オーバーロード（`!`、`~`）によるバインディングアクセス

**関連システム・外部連携**：
- `AvaloniaPropertyRegistry`：プロパティの登録管理
- `AvaloniaObject`：プロパティ値の保持
- `StyledPropertyMetadata`/`DirectPropertyMetadata`：プロパティ設定
- `ValueStore`：値の優先度管理

**権限による制御**：特になし（フレームワーク基盤クラス）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は全画面の基盤となるクラスであり、特定の画面に紐づかない |

## 機能種別

フレームワーク基盤 / プロパティ定義 / メタデータ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | プロパティ名 | null不可、ピリオド含む名前は不可 |
| defaultValue | TValue | No | デフォルト値 | 参照型の場合は共有に注意 |
| inherits | bool | No | 継承プロパティか | - |
| defaultBindingMode | BindingMode | No | デフォルトのバインディングモード | - |
| validate | Func<TValue, bool> | No | バリデーション関数 | - |
| coerce | Func<AvaloniaObject, TValue, TValue> | No | 値補正関数 | - |
| getter | Func<TOwner, TValue> | Yes(Direct) | DirectProperty用の値取得関数 | null不可 |
| setter | Action<TOwner, TValue> | No | DirectProperty用の値設定関数 | - |

### 入力データソース

- コントロールクラスの静的初期化ブロック
- 拡張メソッドによるアタッチドプロパティ定義
- XAMLパーサーによるプロパティ参照

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| StyledProperty<T> | StyledProperty<T> | 登録されたスタイル適用可能なプロパティ |
| AttachedProperty<T> | AttachedProperty<T> | 登録されたアタッチドプロパティ |
| DirectProperty<TOwner, T> | DirectProperty<TOwner, T> | 登録された直接プロパティ |
| Changed | IObservable<AvaloniaPropertyChangedEventArgs> | プロパティ変更のオブザーバブル |

### 出力先

- `AvaloniaPropertyRegistry`への登録
- プロパティ変更監視者への通知

## 処理フロー

### 処理シーケンス

```
1. AvaloniaProperty.Register<TOwner, TValue>()の呼び出し
   └─ 引数のバリデーション（name非null、ピリオード不可）
   └─ StyledPropertyMetadataの作成
   └─ StyledPropertyインスタンスの生成
   └─ AvaloniaPropertyRegistry.Registerで登録

2. AvaloniaProperty.RegisterAttached<TOwner, THost, TValue>()の呼び出し
   └─ AttachedPropertyインスタンスの生成
   └─ Registry.Registerで所有者型に登録
   └─ Registry.RegisterAttachedでホスト型に登録

3. AvaloniaProperty.RegisterDirect<TOwner, TValue>()の呼び出し
   └─ DirectPropertyMetadataの作成
   └─ DirectPropertyインスタンスの生成（getter/setter付き）
   └─ AvaloniaPropertyRegistry.Registerで登録

4. GetMetadata(type)の呼び出し
   └─ _singleMetadataがデフォルトと同じならそのまま返却
   └─ キャッシュから検索、なければ型階層を辿って取得
```

### フローチャート

```mermaid
flowchart TD
    A[Register呼び出し] --> B{引数検証}
    B -->|無効| C[例外スロー]
    B -->|有効| D[メタデータ作成]
    D --> E[プロパティインスタンス生成]
    E --> F[ID採番]
    F --> G[メタデータをFreeze]
    G --> H[Registry.Register]
    H --> I[プロパティ返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | プロパティ名制約 | プロパティ名にピリオドは使用不可 | Register時 |
| BR-02 | 一意ID | 各プロパティは一意のIDを持つ | 常時 |
| BR-03 | メタデータ不変性 | メタデータはFreeze後は変更不可 | 登録後 |
| BR-04 | 参照型デフォルト値の警告 | 参照型のdefaultValueはインスタンス共有される | Register時 |
| BR-05 | メタデータ上書き制約 | 同一型に対して複数回OverrideMetadata不可 | OverrideMetadata時 |

### 計算ロジック

メタデータ取得のキャッシュ戦略：
1. `_singleMetadata`が`_defaultMetadata`と同一ならデフォルトを返却（最速パス）
2. `_singleMetadata`がnullでなく、対象型がホスト型のサブクラスなら`_singleMetadata`返却
3. `_metadataCache`から型をキーに検索
4. キャッシュミスなら型階層を辿り、見つかったメタデータをキャッシュ

## データベース操作仕様

該当なし（メモリ内データ構造のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentNullException | name/getter等がnull | 必須引数を指定 |
| - | ArgumentException | プロパティ名にピリオード含む | ピリオードを除去 |
| - | InvalidOperationException | 同一型にメタデータを複数回オーバーライド | オーバーライドは1回のみ |
| - | NotSupportedException | 不正なプロパティ型 | 対応する派生クラスを使用 |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし（メモリ内操作のみ）

## パフォーマンス要件

- プロパティIDによる高速比較（整数比較のみ）
- メタデータ取得はキャッシュにより高速化
- 型階層の走査は初回のみで、以降はキャッシュ利用

## セキュリティ考慮事項

- プロパティ定義は静的初期化時に行われ、ランタイム中の変更は制限される
- メタデータのFreezeにより不変性を保証

## 備考

- WPF互換の設計だが、パフォーマンス最適化のための独自拡張あり
- `UnsetValue`は未設定状態を表す特殊なシングルトン

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

プロパティ定義の基本構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AvaloniaProperty.cs | `src/Avalonia.Base/AvaloniaProperty.cs` | 基底クラスの構造、ID、メタデータ辞書 |
| 1-2 | AvaloniaPropertyMetadata.cs | `src/Avalonia.Base/AvaloniaPropertyMetadata.cs` | メタデータの基本構造 |

**読解のコツ**: `Id`プロパティが各プロパティの一意識別子であり、`Equals`や`GetHashCode`で使用されることを把握する。

#### Step 2: プロパティ登録を理解する

`Register`系メソッドの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AvaloniaProperty.cs | `src/Avalonia.Base/AvaloniaProperty.cs` | Register静的メソッド群 |

**主要処理フロー**:
1. **253-280行目**: `Register<TOwner, TValue>`でStyledPropertyを登録
2. **355-376行目**: `RegisterAttached<TOwner, THost, TValue>`でアタッチドプロパティを登録
3. **439-463行目**: `RegisterDirect<TOwner, TValue>`でDirectPropertyを登録

#### Step 3: 派生クラスを理解する

プロパティの種類ごとの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | StyledProperty.cs | `src/Avalonia.Base/StyledProperty.cs` | スタイル適用可能なプロパティ |
| 3-2 | DirectPropertyBase.cs | `src/Avalonia.Base/DirectPropertyBase.cs` | バッキングフィールドを持つプロパティ |
| 3-3 | AttachedProperty.cs | `src/Avalonia.Base/AttachedProperty.cs` | アタッチドプロパティの特性 |

**主要処理フロー**:
- StyledProperty: ValueStoreを介して値を管理
- DirectProperty: getter/setterを直接呼び出し

#### Step 4: メタデータ管理を理解する

型別のメタデータ取得とオーバーライドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AvaloniaProperty.cs | `src/Avalonia.Base/AvaloniaProperty.cs` | GetMetadata、OverrideMetadataメソッド |

**主要処理フロー**:
- **504-521行目**: `GetMetadata(Type)`でキャッシュを利用したメタデータ取得
- **633-652行目**: `OverrideMetadata`でメタデータの上書き

### プログラム呼び出し階層図

```
AvaloniaProperty（抽象基底）
    │
    ├─ StyledProperty<T>（スタイル適用可能）
    │      └─ AttachedProperty<T>（アタッチド）
    │
    └─ DirectPropertyBase<T>（直接プロパティ基底）
           └─ DirectProperty<TOwner, T>（具象クラス）

AvaloniaPropertyRegistry
    └─ プロパティの型別登録管理

AvaloniaPropertyMetadata
    ├─ StyledPropertyMetadata<T>
    └─ DirectPropertyMetadata<T>
```

### データフロー図

```
[入力]                     [処理]                          [出力]

Register(name, defaultValue, ...)
        │
        ▼
   引数検証 ─────────▶ ArgumentException（無効時）
        │
        ▼
   メタデータ作成
        │
        ▼
   Freeze（不変化）
        │
        ▼
   ID採番（s_nextId++）
        │
        ▼
   Registry.Register ───▶ AvaloniaPropertyRegistry
        │
        ▼
   プロパティ返却 ─────▶ StyledProperty<T> / DirectProperty<T>
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AvaloniaProperty.cs | `src/Avalonia.Base/AvaloniaProperty.cs` | ソース | プロパティ定義の抽象基底クラス |
| StyledProperty.cs | `src/Avalonia.Base/StyledProperty.cs` | ソース | スタイル適用可能なプロパティ |
| DirectPropertyBase.cs | `src/Avalonia.Base/DirectPropertyBase.cs` | ソース | 直接プロパティの基底 |
| DirectProperty.cs | `src/Avalonia.Base/DirectProperty.cs` | ソース | 直接プロパティの具象クラス |
| AttachedProperty.cs | `src/Avalonia.Base/AttachedProperty.cs` | ソース | アタッチドプロパティ |
| AvaloniaPropertyMetadata.cs | `src/Avalonia.Base/AvaloniaPropertyMetadata.cs` | ソース | メタデータ基底 |
| StyledPropertyMetadata.cs | `src/Avalonia.Base/StyledPropertyMetadata.cs` | ソース | StyledProperty用メタデータ |
| AvaloniaPropertyRegistry.cs | `src/Avalonia.Base/AvaloniaPropertyRegistry.cs` | ソース | プロパティ登録管理 |
| UnsetValueType.cs | `src/Avalonia.Base/AvaloniaProperty.cs` | ソース | 未設定値を表す型（721-730行目） |
