# 機能設計書 90-MarkupExtension

## 概要

本ドキュメントは、Avaloniaフレームワークにおける「MarkupExtension」機能の設計仕様を記述する。MarkupExtensionは、XAML内で`{Binding}`や`{StaticResource}`などの特殊な構文を実現するための基盤クラスであり、マークアップ拡張の抽象基底クラスを提供する。

### 本機能の処理概要

MarkupExtensionは、XAMLパーサーが`{...}`構文を検出した際に呼び出される拡張ポイントを定義する。各マークアップ拡張は、ProvideValueメソッドを実装し、IServiceProviderを通じてXAMLコンテキストにアクセスして、動的に値を生成する。これにより、データバインディング、リソース参照、相対ソース指定などの高度なXAML機能が実現される。

**業務上の目的・背景**：XAMLの表現力を拡張し、単純な属性値設定では実現できない動的な値の提供を可能にする。Bindingによるデータバインディング、StaticResourceによるリソース参照、DynamicResourceによる動的リソース参照など、MVVMパターンやテーマ切り替えの基盤となる重要な機能である。

**機能の利用シーン**：データバインディング（{Binding}）、静的リソース参照（{StaticResource}）、動的リソース参照（{DynamicResource}）、相対ソース指定（{RelativeSource}）、型参照（{x:Type}）で利用される。

**主要な処理内容**：
1. IServiceProviderを通じたXAMLコンテキストへのアクセス
2. ProvideValueによる値の提供
3. ターゲットオブジェクト・プロパティへの適用
4. 遅延バインディングのサポート

**関連システム・外部連携**：XamlLoader、IProvideValueTarget、IXamlTypeResolver、BindingExpressionと連携する。

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全画面 | 補助機能 | XAML拡張構文の処理 |

## 機能種別

抽象クラス / 拡張ポイント

## 入力仕様

### 入力パラメータ

**ProvideValue**:
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| serviceProvider | IServiceProvider | Yes | XAMLサービスプロバイダー | - |

### 入力データソース

XAMLパーサーからの呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | object | 提供される値（バインディング、リソース等） |

### 出力先

XAMLで指定されたプロパティ

## 処理フロー

### 処理シーケンス

```
1. XAMLパーサーが{...}構文を検出
   └─ マークアップ拡張クラスをインスタンス化
   └─ 属性をプロパティに設定

2. ProvideValue呼び出し
   └─ IServiceProviderからサービスを取得
   └─ IProvideValueTargetでターゲット情報を取得
   └─ 値を計算または遅延バインディングを設定

3. 値の適用
   └─ 直接値の場合: プロパティに設定
   └─ バインディングの場合: BindingExpressionを返却
   └─ 遅延の場合: DelayedBindingを登録
```

### フローチャート

```mermaid
flowchart TD
    A["{Extension}"構文検出] --> B[MarkupExtensionインスタンス化]
    B --> C[プロパティ設定]
    C --> D[ProvideValue呼び出し]
    D --> E{拡張タイプ}
    E -->|StaticResource| F[リソース検索]
    E -->|DynamicResource| G[DynamicResourceExpression作成]
    E -->|Binding| H[BindingExpression作成]
    E -->|その他| I[カスタム処理]
    F --> J{見つかった?}
    J -->|Yes| K[値を返却]
    J -->|No| L[DelayedBinding登録]
    G --> M[バインディング返却]
    H --> M
    I --> K
    L --> N[後で解決]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | abstract実装 | ProvideValueは派生クラスで実装必須 | 全マークアップ拡張 |
| BR-002 | サービス取得 | serviceProvider.GetService<T>()でサービス取得 | ProvideValue内 |
| BR-003 | UnsetValue | 遅延解決の場合はAvaloniaProperty.UnsetValueを返却 | StaticResource等 |
| BR-004 | テーマバリアント | IThemeVariantHostからActualThemeVariantを取得 | リソース解決時 |

### 計算ロジック

該当なし（派生クラスで実装）

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentException | StaticResourceExtension.ResourceKeyがnull | ResourceKeyを設定 |
| - | InvalidOperationException | DynamicResourceExtension.ResourceKeyがnull | ResourceKeyを設定 |
| - | KeyNotFoundException | StaticResourceでリソースが見つからない | リソースを定義 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- StaticResourceExtension.ProvideValueはインライン化を促進
- EagerParentStackEnumeratorでアロケーションを削減
- ColorToBrushConverterで一般的な変換を最適化

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

特になし

## 備考

主要な実装クラス：
- StaticResourceExtension: 静的リソース参照
- DynamicResourceExtension: 動的リソース参照
- CompiledBindingExtension: コンパイル済みバインディング
- ReflectionBindingExtension: リフレクションバインディング

---

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

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

### 推奨読解順序

#### Step 1: 基底クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MarkupExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtension.cs` | 抽象クラス定義（5-8行目） |

**読解のコツ**: MarkupExtensionは非常にシンプルな抽象クラス。派生クラスでProvideValueを実装する設計。

#### Step 2: StaticResourceExtensionを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | StaticResourceExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs` | クラス定義と主要処理 |

**主要処理フロー**:
1. **25行目**: ResourceKeyプロパティ
2. **29行目**: ProvideValueメソッド（インスタンス版、インライン化促進）
3. **32-109行目**: ProvideValue静的メソッド（実装本体）
4. **39行目**: IAvaloniaXamlIlParentStackProviderでスタック取得
5. **66-93行目**: 親をたどってリソースを検索
6. **103-106行目**: 見つからない場合、DelayedBindingを登録

#### Step 3: DynamicResourceExtensionを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DynamicResourceExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs` | 動的リソース拡張 |

**主要処理フロー**:
1. **11行目**: BindingBaseを継承
2. **27行目**: ResourceKeyプロパティ
3. **29-47行目**: ProvideValueでBindingBaseを返却
4. **49-54行目**: CreateInstanceでDynamicResourceExpressionを作成

#### Step 4: サービスプロバイダーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | IAvaloniaXamlIlParentStackProvider.cs | `src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/IAvaloniaXamlIlParentStackProvider.cs` | 親スタックプロバイダー |
| 4-2 | XamlIlRuntimeHelpers.cs | `src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs` | ランタイムヘルパー |

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

```
MarkupExtension (抽象基底クラス)
    │
    ├─ abstract ProvideValue(IServiceProvider)
    │
    └─ 派生クラス
           │
           ├─ StaticResourceExtension
           │      ├─ ProvideValue (インスタンス)
           │      │      └─ ProvideValue (静的)
           │      │             ├─ IAvaloniaXamlIlParentStackProvider.Parents
           │      │             ├─ IResourceNode.TryGetResource
           │      │             └─ DelayedBinding.Add (遅延)
           │      └─ GetDictionaryVariant
           │
           ├─ DynamicResourceExtension
           │      ├─ ProvideValue
           │      │      └─ BindingBase返却
           │      └─ CreateInstance
           │             └─ DynamicResourceExpression
           │
           ├─ CompiledBindingExtension
           │      └─ ProvideValue
           │             └─ CompiledBindingPath
           │
           └─ ReflectionBindingExtension
                  └─ ProvideValue
                         └─ Binding
```

### データフロー図

```
[XAML]                    [処理]                         [出力]

{StaticResource Key}
        │
        ▼
MarkupExtension.ProvideValue
        │
        ├─ IServiceProvider
        │      ├─ IProvideValueTarget (ターゲット情報)
        │      └─ IAvaloniaXamlIlParentStackProvider (親スタック)
        │
        ▼
リソース検索 ─────────────────────────────────────────▶ 値
        │
        └─ 見つからない場合 ───▶ DelayedBinding ───▶ 後で解決
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MarkupExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtension.cs` | ソース | 抽象基底クラス |
| StaticResourceExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs` | ソース | 静的リソース |
| DynamicResourceExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs` | ソース | 動的リソース |
| CompiledBindingExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs` | ソース | コンパイル済みバインディング |
| ReflectionBindingExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs` | ソース | リフレクションバインディング |
| RelativeSourceExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/RelativeSourceExtension.cs` | ソース | 相対ソース |
| OnPlatformExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs` | ソース | プラットフォーム分岐 |
| OnFormFactorExtension.cs | `src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnFormFactorExtension.cs` | ソース | フォームファクター分岐 |
| DynamicResourceExpression.cs | `src/Markup/Avalonia.Markup.Xaml/Data/DynamicResourceExpression.cs` | ソース | 動的リソース式 |
