📘

.NET 8 リフレクションベースのシリアライゼーションに関する破壊的変更

2024/07/01に公開

.NET 8 リフレクションベースのシリアライゼーションに関する破壊的変更

概要

.NET 8では、PublishTrimmed [1]プロジェクトでリフレクションベース[2]のシリアライゼーション[3][4]が自動的に無効化されるようになりました。この変更により、特定の条件下でシリアライゼーションが失敗することがあります。

変更内容の詳細

.NET 8以降、PublishTrimmed プロパティが有効なプロジェクトでは、リフレクションベースのシリアライゼーションがデフォルトで無効になります。このプロパティが有効になっている場合、プロジェクトファイルで特に指定しない限り、次のコードは例外をスローします。

JsonSerializer.Serialize(new { Value = 42 });

このコードは、以下の例外をスローします。

System.InvalidOperationException: Reflection-based serialization has been disabled for this application.

変更理由

この変更は、ソースジェネレーターを使用し、安全でないリフレクションベースのコンポーネントへの依存を避けるためです。これにより、トリミングされたアプリケーションでの動作がより予測可能になり、ベストプラクティスの適用が促進されます。

推奨される操作

シリアライゼーションを正常に実行するためには、以下のいずれかの方法を採用することをお勧めします。

  1. ソースジェネレーターの使用: トリミングされたアプリケーションで安全かつ効率的にシリアライゼーションを行うために、ソースジェネレーターを使用します。
  2. リフレクションベースのシリアライゼーションを有効にする: プロジェクトファイルで JsonSerializerIsReflectionEnabledByDefault プロパティを明示的に有効にします。

プロジェクトファイルの設定

プロジェクトファイル (.csproj) に以下の設定を追加して、リフレクションベースのシリアライゼーションを有効にします。

<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>

GPT-4による解説

PublishTrimmedのプロパティとは

「PublishTrimmed」というのは、.NETというプログラミングのツールで使われる設定の一つです。この設定を使うと、プログラムが軽く、速く動くようになります。

プロジェクトファイル (.csproj) に以下の設定をすることでオフにできます。

<PropertyGroup>
  <PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>

単一EXEファイルを作成するためのコマンドラインオプションにPublishTrimmedが含まれている場合があります。

dotnet publish -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:PublishTrimmed=false

コマンドオプションの説明

  • -c Release: リリースモードでビルド
  • -r win-x64: ターゲットランタイムを指定
  • --self-contained true: 自己完結型のEXEを作成
  • /p:PublishSingleFile=true: 単一ファイルにパブリッシュ
  • /p:PublishTrimmed=false: トリミングを無効化

リフレクション

リフレクションとは、プログラムが実行時に自分自身の構造(クラスやメソッドなど)を調べたり変更したりする機能のことです。例えば、プログラムが自分で「このクラスにはどんなメソッドがあるのか」を確認するようなことです。

シリアライゼーション

シリアライゼーションとは、プログラムのデータを保存したり送信したりするために、データを一つの形式に変換することです。例えば、オブジェクト(プログラム内のデータ)をJSONやXMLなどの形式に変換することを指します。

リフレクションベースのシリアライゼーション

リフレクションベースのシリアライゼーションは、プログラムが実行時にリフレクションを使って、オブジェクトの構造を調べて、自動的にシリアライゼーションを行うことです。簡単に言うと、プログラムが「このオブジェクトにはこんなデータがあるから、こういう形式に変換しよう」と考えることです。

なぜ問題になるのか?

  • .NET 8 以降の変更: .NET 8 以降では、プログラムを小さくして早く動かすために、不要な部分を取り除く「トリミング」が行われます。このとき、リフレクションを使ったシリアライゼーションはデフォルトで無効になります。
  • エラーの原因: リフレクションベースのシリアライゼーションが無効になると、プログラムが自動的にデータの構造を調べてシリアライゼーションすることができなくなり、エラーが発生します。

解決策

  1. リフレクションベースのシリアライゼーションを有効にする: プロジェクト設定でリフレクションを使えるようにする。
  2. ソースジェネレーターを使う: プログラムの構造を事前に調べて、必要なシリアライゼーションコードを自動生成する方法です。

参考文献

(.NET 8の破壊的変更)PublishedTrimmed プロジェクトがリフレクション ベースのシリアル化に失敗する
https://learn.microsoft.com/ja-jp/dotnet/core/compatibility/serialization/8.0/publishtrimmed

脚注
  1. 「PublishTrimmed」というのは、.NETというプログラミングのツールで使われる設定の一つです。この設定を使うと、プログラムが軽く、速く動くようになります。 ↩︎

  2. リフレクションとは、プログラムが実行時に自分自身の構造(クラスやメソッドなど)を調べたり変更したりする機能のことです。例えば、プログラムが自分で「このクラスにはどんなメソッドがあるのか」を確認するようなことです。 ↩︎

  3. シリアライゼーションとは、プログラムのデータを保存したり送信したりするために、データを一つの形式に変換することです。例えば、オブジェクト(プログラム内のデータ)をJSONやXMLなどの形式に変換することを指します。 ↩︎

  4. リフレクションベースのシリアライゼーションは、プログラムが実行時にリフレクションを使って、オブジェクトの構造を調べて、自動的にシリアライゼーションを行うことです。簡単に言うと、プログラムが「このオブジェクトにはこんなデータがあるから、こういう形式に変換しよう」と考えることです。 ↩︎

Discussion