ストアの落とし穴 #4:.NET のトリミングが WinUI 3 のバインディングを消し去った
2026-05-31
Tags: Windows · Microsoft Store · ストアの落とし穴
これはかなり初期に遭遇した問題です。この落とし穴シリーズを書くために古いメールを漁っていたところ、ずっと前に届いていたリジェクト通知を見つけました——この記録が、WinUI 3 / .NET の公開プロセスに初めて触れる開発者の参考になれば幸いです。
何が起きたか
私の WinUI 3 アプリの一つを Microsoft Store の認定に提出しました。認定レポートが返ってきました:
Status: Attention needed
10.1.2.10 Functionality
Unusable Feature: "Download to local cache", "Open File" - The product fails to download copied items to local cache and "Open File" button in the product is not usable
待ってください——ローカルではちゃんとテスト済みでした。「ローカルキャッシュにダウンロード」と「ファイルを開く」はどちらも正常に動作していました。なぜマイクロソフトのテスト環境では動かないのでしょうか?
調査
最も怪しい違いは、ローカルでは Debug ビルドを使っていましたが、ストア提出は Release ビルドだったことです。.csproj ファイルを確認すると、Debug と Release の構成間に重大な違いがありました:
<!-- Debug -->
<PublishTrimmed>False</PublishTrimmed>
<!-- Release -->
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>Release ビルドでは .NET トリミング(Trimming)が有効になっていました。
.NET トリミングとは
.NET トリミングは .NET SDK が提供する最適化機能です。アプリを公開する際、トリマーは静的解析を行い、コード内で直接参照されていないアセンブリ、型、メソッドを見つけて削除し、アプリサイズを縮小します。
問題点:トリマーは静的参照しか認識できません。コードがリフレクションを使って実行時に型を呼び出している場合、コンパイル時にその型への静的参照がなければ、トリマーはその型を「未使用」と見なして削除してしまいます。
なぜ WinUI 3 が特に影響を受けやすいか
WinUI 3 とその基盤となる WinRT 相互運用レイヤーは、リフレクションと動的機能に大きく依存しています。従来の {Binding}、値コンバーター、WinRT 相互運用メタデータリフレクションはすべて、トリマーの静的解析では追跡できない実行時呼び出しを発生させます。トリマーがバインディングに依存するデータモデル、コマンド、コンバーターなどの型を「未使用」として削除すると、実行時にバインディングがターゲットを見つけられず、UI のボタンやテキスト更新が黙って機能しなくなります——エラーも出ず、クラッシュもせず、ただ動かなくなるだけです。
解決策
最もシンプルな方法:.csproj でトリミングを無効にします:
- <PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
+ <PublishTrimmed>False</PublishTrimmed>再パッケージして再提出すると、認定に通りました。
パッケージサイズを削減するためにトリミングが必要な場合は、以下の方法で対応することも可能です:
- 必要な型に
[DynamicDependency]または[DynamicallyAccessedMembers]属性を付与して、トリマーに保持を指示する .csprojで<TrimmerRootAssembly>を設定してアセンブリ全体を保持する
ただし、ほとんどの WinUI 3 アプリでは、トリミングを無効にするのが最も安全な選択です。
まとめ
- .NET トリミングは「未使用」と判断したコードを削除しますが、リフレクションベースの呼び出しを検出できません
- WinUI 3 のデータバインディングはリフレクションに依存しているため、誤ってトリミングされやすいです
- WinUI 3 アプリがストア認定で「機能が使用不可」と失敗するがローカルでは正常に動作する場合、最初に疑うべきはトリミングです
- Debug ビルドはデフォルトでトリミングされませんが、Release ビルドではトリミングが有効になる場合があります——ストア提出前に必ず Release/Publish ビルドでテストしてください
- ストア提出前のテストに関するヒントをまとめたフォローアップ記事を予定しています。お楽しみに
この記事はストアの落とし穴シリーズの一部です。