はじめに
アプリケーションを開発している際に何かの設定ファイルや画像などのリソースも一緒に配布したいときがあると思います。.NETでは以下のような組み込み方法があります。
EmbeddedResource
CopyToPublishDirectory
やCopyToOutputDirectory
それぞれについて解説した後、簡単な比較を行いたいと思います。
概要
EmbeddedResource
EmbeddedResource
はアセンブリ(.dll
や.exe
)の中に直接ファイルを組み込む手法です。
<!-- csprojに下記を記載してリソースを組み込む --> <ItemGroup> <EmbeddedResource Include="./sample.txt" LogicalName="sample.txt" /> </ItemGroup>
// Program.cs using System.Reflection; var assembly = Assembly.GetExecutingAssembly(); using var stream = assembly.GetManifestResourceStream("sample.txt"); if (stream == null) { throw new FileNotFoundException("Resource not found: sample.txt"); } using var streamReader = new StreamReader(stream); var content = streamReader.ReadToEnd(); Console.WriteLine(content);
EmbeddedResource
には以下のメリットがあります。
- アセンブリに組み込まれるため配布が楽
- ユーザーによる編集がしにくい
逆にデメリットは以下でしょうか。
- アセンブリサイズの肥大化
- コンパイル時以外に編集不可
- アクセス方法が特殊
CopyToPublishDirectory & CopyToOutputDirectory
CopyToPublishDirectory
やCopyToOutputDirectory
はビルド時またはパブリッシュ時に、指定されたファイルを実行ファイルと同じディレクトリ(またはサブディレクトリ)にコピーする方法です。
CopyToOutputDirectory
:dotnet build
実行時CopyToPublishDirectory
:dotnet publish
実行時
CopyToOutputDirectory
を定義した場合は、bin\Debug\net8.0\
やbin\Release\net8.0\
といったパスにもファイルが吐き出されます。逆にCopyToPublishDirectory
のみ定義している場合はdotnet run
を実行しても吐き出されません。
<!-- csprojに下記を記載してリソースを組み込む --> <ItemGroup> <Content Include="./sample.txt" > <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> </Content> </ItemGroup>
// Program.cs var path = Path.Combine(AppContext.BaseDirectory, "sample.txt"); if (File.Exists(path)) { Console.WriteLine("File exists."); } else { Console.WriteLine("File does not exist."); }
メリットは以下あたりでしょうか。
- アセンブリのファイルサイズを抑えることができる
- コンパイル後にも中身を編集ができる
- アクセス手法が簡単
逆にデメリットもあります。
- デプロイが比較的複雑になる
- ファイルの消失・改ざんのリスク
- パスの管理が必要
どちらを利用すべきか
以下が重要な観点になると思います。
- ユーザーがファイルを編集しても良いかどうか
- ファイルの変更が頻繁にあるかどうか
EmbeddedResource
はファイルがアセンブリに組み込まれるので編集は基本的にできません。しかしユーザーに編集をしてもらいたい場合には困るでしょう。開発者が中身を編集したい場合には、再度コンパイルしてユーザーへと配布する必要がでてきますが、CopyToPublishDirectory
やCopyToOutputDirectory
はアセンブリに変更がなければコンパイルの必要はありません。
また一応ユーザーに見られては困るファイルはEmbeddedResource
にしておいた方が比較的知られずらいですが、中身をみようと思ったら割と簡単に見れるのでまあ気休め程度だとは思っておいた方が無難です。