物理ファイルには、濃度をコンパイルされたリソースとしてプログラムに直接埋め込むことができます。EmbeddedFileProviderにより、我々は、プログラミングへの統一的なアプローチを採用することができ、埋め込みリソースファイルを読み、タイプは「Microsoft.Extensions.FileProviders.Embedded」NuGetこのパッケージで定義されています。正式導入EmbeddedFileProviderに先立ち、我々はプロジェクトファイルに埋め込まれたプログラムに内部リソースとして濃度をコンパイル方法を知っている必要があります。
まず、このプロジェクトは、埋め込まれたリソースファイルになります
デフォルトでは、我々は、.NETのコアプロジェクトは、アセンブリターゲットに埋め込まれたリソースファイルになっていない静的なファイルに追加します。あなたが埋め込まれたターゲットアセンブリのような静的ファイルを提出する必要がある場合、我々は、現在のプロジェクトに対応する.csprojファイルを変更する必要があります。具体的には、前の例.csprojファイル<ItemGroup> / <EmbeddedResource>要素で実証された方法で追加する必要がある、と明示的に含まれるリソースファイルを対応する属性を含めるを使用します。Actionプロパティリソースファイルを構築するために、我々の直接の使用のVisual Studioは、「埋め込まれたリソース」に設定されている場合、IDEは自動的にプロジェクトファイルを変更するために私たちを助けます。
<EmbeddedResource>プロパティを含めるには、(「;」)セミコロンを使用して、パスを複数のパスを提供することができるセパレータとして。上記で図に示した例ディレクトリ構造、我々はアセンブリ埋め込みファイルにファイルの4つのrootディレクトリが必要な場合、我々は、.csprojファイルを修正して含まれる4つのファイルのパスの形をたどることができます。
< プロジェクトSDK = "Microsoft.NET.Sdk" > ... < ItemGroup > < EmbeddedResource 含める= "ルート/ DIR1 / foobarに/ foo.txtの、ルート/ DIR1 / foobarに/ bar.txt;ルート/ DIR1 / baz.txt;ルート/ DIR2 / qux.txt" > </ EmbeddedResource > < / ItemGroup > </ プロジェクト>
各埋め込みリソースファイルの外のパスを指定する必要性に加えて、我々はまた、ワイルドカード「*」と付属のバッチファイルのセットに一致するグロブパターンの「**」という表現をベースとすることができます。また、アセンブリのルートディレクトリ内のすべてのファイル埋め込みファイルとして、以下の定義がはるかに簡潔な方法になります。
< プロジェクトSDK = "Microsoft.NET.Sdk" > ... < ItemGroup > < EmbeddedResource 含める= "ルート/ **" > </ EmbeddedResource > </ ItemGroup > </ プロジェクト>
<EmbeddedResource>は有することに加えて、それはまた別のファイルが除外の要件を満たしていない責任属性除外あり、埋め込まれたリソースファイルを追加するには、属性を含めます。私たちは、埋め込みリソースファイルとしてbaz.txtファイルをしたくない場合や、プロジェクトの前に、例えば、ルートディレクトリにある4つのファイルのために、我々は次のような方法は、それを除外従うことができます。
< プロジェクトSDK = "Microsoft.NET.Sdk" > ... < ItemGroup > < EmbeddedResource 含める= "ルート/ **" 除外= "ルート/ DIR1 / baz.txt" > </ EmbeddedResource > </ ItemGroup > </ プロジェクト>
第二に、リソースファイルを読み込みます
各アセンブリは、マニフェストファイル(マニフェスト)を持って、その重要な役割の一つは、アセンブリのすべてのファイル・メンバーを記録することです。一般的に、アセンブリは主に埋め込まれたファイルとILコードリソースファイルを保有するコンパイルされたモジュールを管理しているファイルの2種類で構成されています。上に示したプロジェクト構造のために、我々はリソースファイルの形で組み立て生成された4つのテキストファイル(App.dll)に組み込まれた場合、アセンブリのマニフェストファイルは、レコードには下記のフォームをとりますそれら。
公共App.root.dir1.baz.txt .mresource
{
//オフセット:0x00000000の長さ:0x0000000C
}
公共App.root.dir1.foobar.bar.txt .mresource
{
//オフセット:0x00000010長さ:0x0000000C
}
公共App.root.dir1.foobar.foo.txt .mresource
{
//オフセット:0x00000020長さ:0x0000000C
}
公共App.root.dir2.qgux.txt .mresource
{
//オフセット:0x00000030長さ:0x0000000C
}
ファイルは、元のプロジェクトでの階層ディレクトリ構造を持っていますが、彼らが正常に組み立てた後にコンパイルに転送されたときに、ディレクトリ構造が存在しなくなりますが、すべてのファイルが同じコンテナに埋め込まれた統一に保存されます。私たちはリフレクターによってアセンブリを開くと、フラット・ファイル・ストレージ・リソースがより明らかになるであろう。名前の競合を避けるために、コンパイラは、元のファイルは、リソースファイルの名前を変更するためのパスに基づいて行われます、特定のルールが「されている{BaseNamespace}。{パス}」、ディレクトリの区切り変換を統一します。「」それは価値があることを名前の接頭辞ではないアセンブリのリソース・ファイル名を強調しているが、我々は、プロジェクトの設定根拠の名前空間の名前を。
アセンブリオブジェクトは、アセンブリ表す関連情報埋め込みリソースファイルを抽出し、指定されたリソースファイルの内容を読み取るには、次のいくつかの方法を定義します。GetManifestResourceNames方法私たちは、リソース・ファイル名を得るためには、アセンブリマニフェストファイルに書き込まれ、そして他の方法はGetManifestResourceInfoは、リソースファイルの説明を指定した取得するために使用されます。私たちは、リソースファイルの内容を読み取るために必要がある場合、我々は、引数としてリソース・ファイル名を呼び出すことができGetManifestResourceStreamのファイルの内容を読み取るためにStreamオブジェクトを返すメソッド、。
パブリック 抽象 クラスアセンブリ { パブリック 仮想 列[] GetManifestResourceNames()。 パブリック 仮想 ManifestResourceInfo GetManifestResourceInfo(文字列resourceNameは); パブリック 仮想ストリームGetManifestResourceStream(文字列名)。 }
同じことは、4つのファイルが正常に埋め込まれたファイルとして、コンパイラが生成するアセンブリに移したとき、私たちはファイルに埋め込まれたこれら4つのオブジェクトのリソースへのアクセスの組み立て方法GetManifestResourceNamesを呼び出すことができますに対応する実証プロジェクトのディレクトリ構造のフロント用です名前。リソース名(「App.root.dir1.foobar.foo.txt」)は、パラメータとしてGetManifestResourceStreamメソッドを呼び出す場合、我々は、リソースファイルの内容を読み取ることができ、特定のプレゼンテーションは以下の通りです。
クラスプログラム { 静的な 無効メイン() { varがアセンブリ= typeof演算.Assembly(プログラム)。 VAR resourceNameの= assembly.GetManifestResourceNames()。 Debug.Assertの(resourceNames.Contains(" App.root.dir1.foobar.foo.txt " )); Debug.Assertの(resourceNames.Contains(" App.root.dir1.foobar.bar.txt " )); Debug.Assertの(resourceNames.Contains(" App.root.dir1.baz.txt " )); Debug.Assertの(resourceNames.Contains(" App.root.dir2.qgux.txt " )); VaRの流れ= assembly.GetManifestResourceStream(" App.root.dir1.foobar.foo.txt " ); VaRのバッファは= 新しい バイトを[のStream.length]。 stream.Read(バッファ、0 、buffer.Length)。 VaRの含有量= Encoding.Default.GetString(バッファ) Debug.Assertの(コンテンツ == File.ReadAllText(" アプリケーション/ルート/ DIR1 / foobarに/ foo.txtの" )); } }
三、EmbeddedFileProvider
アセンブリは、リソースファイルに埋め込まれた後、あなたはEmbeddedFileProvider非常によく理解の原則の実施のための一般的な理解を持っています。アセンブリは、リソースファイルに埋め込まれているのでEmbeddedFileProviderは、ファイルシステムによって構成され、ディレクトリ階層の概念がないので、フラットの形で格納されます。私たちは、ファイルを組み立て、「ルートディレクトリ」に保存されているすべてのリソースと考えることができます。EmbeddedFileProviderビルドファイルシステム、それは常にEmbeddedResourceFileInfoを有する対象と定義される特定のリソースファイルの記述を提供することIFileInfoオブジェクトの。
パブリック クラスEmbeddedResourceFileInfo:IFileInfo { プライベート 読み取り専用組立_assembly。 プライベート 長いですか?_length; プライベート 読み取り専用 の文字列 _resourcePath。 公共 EmbeddedResourceFileInfo(組立組立、文字列 resourcePath、列名、のDateTimeOffset LASTMODIFIED) { _assembly = アセンブリ。 _resourcePath = resourcePath。 この .NAME = 名前; この .LastModified = LASTMODIFIED。 } 公共ストリームCreateReadStream() { ストリームstream = _assembly.GetManifestResourceStream(_resourcePath)。 もし(!この._length.HasValue) { この ._length = 新 長期?(のStream.length)。 } リターンストリーム; } パブリック ブール値 =>存在true ; パブリック ブール IsDirectory => falseを。 公共のDateTimeOffset LastModifiedの{ 取得します。} パブリック 文字列名前{ 取得します。} パブリック 文字列 PhysicalPathの=> ヌル。 公共 長い長さ { 取得する { もし(!_length.HasValue) { 使用(ストリームstream = _assembly.GetManifestResourceStream(この._resourcePath)) { _length = のStream.length。 } } rReturn _length.Value; } } }
上記コードフラグメントに示されているように、我々は、アセンブリは、リソース・ファイル名(名前)、ファイルが最後EmbeddedResourceFileInfoオブジェクトを作成する時に変更されたマニフェストファイル(resourcePath)へのパスに埋め込まれたリソースファイルを指定する必要がありますDateTimeOffsetは時間のオブジェクト。プロパティは常にTrueを返し、IsDirectoryプロパティはFalseを返す存在ですのでEmbeddedResourceFileInfoオブジェクトのためには、常に特定の埋め込みリソースファイルに対応しています。リソース・ファイル・システムので、物理パス無意味と呼ばれる、階層ディレクトリ構造を持っているので、PhysicalPathの直接プロパティはnullを返していません。CreateReadStreamメソッド戻り、メソッド呼び出しが出力ストリームを返し、ファイル長の長さが返されたストリームオブジェクトの長さを示す組立GetManifestResourceStream。
EmbeddedFileProviderは、以下のように定義されます。我々はEmbeddedFileProviderオブジェクトを作成すると、離れて組み立てどこリソースファイルを指定したから、あなたはベースの名前空間を指定することができます。名前空間は次のように明示的に設定されていない場合、デフォルトは名前空間として組み立てケース名になりますが、このEmbeddedFileProviderのオブジェクトを作成するときに我々はそう、基礎名前空間を設定するプロジェクトの名前からプログラムの異なるを指定した場合、つまり、ときに、名前空間を指定する必要があります。
パブリック クラスEmbeddedFileProvider:IFileProvider { 公共EmbeddedFileProvider(アセンブリアセンブリ)。 公共 EmbeddedFileProvider(組立組立、文字列baseNamespace)。 公共 IDirectoryContentsのGetDirectoryContents(文字列サブパス)。 公共 IFileInfo GetFileInfo(文字列サブパス)。 公共 IChangeTokenウォッチ(文字列パターン)。 }
我々はGetFileInfoメソッドのEmbeddedFileProviderを呼び出し、それが一緒にリソースファイルの名前に名前空間がアセンブリマニフェストますリソースファイルの論理名、指定した場合(パスセパレータが置き換えられますが、「」)。対応するリソースファイルが存在する場合、EmbeddedResourceFileInfoが作成されて返され、それ以外のリターンはNotFoundFileInfoオブジェクトになります。それは腕時計の方法は、プロパティは常にIChangeTokenオブジェクトの偽HASCHANGEDで返しますので、埋め込まれたリソース・ファイル・システムの場合、問題は、いわゆるファイルの更新を存在しません。
アセンブリリソースファイルに埋め込まれているので、常に読み取り専用で、それが最後の更新日時が実際にEmbeddedFileProviderように、オブジェクトがリソースファイルとしてアセンブリファイルを最後に更新EmbeddedResourceFileInfoを提供するために使用されるとき、アセンブリ生成していると呼ばれます最終更新時間。あなたは正しくこの時間を解析することができない場合は、EmbeddedResourceFileInfo LastModifiedプロパティは、現在のUTC時刻に設定されます。
空の文字列は、アセンブリのすべての「ルートディレクトリ」に保存されているとして、それが私たちのGetDirectoryContentsでのみですので、そのため階層ディレクトリ構造に構築EmbeddedFileProvider埋め込まれたリソース・ファイル・システムに存在しないの、リソースファイルがすべてのメソッドは、指定され、見ることができますか「/」(空の文字列と「/」手段「ルート」)は実際にオブジェクトEmbeddedResourceFileInfoの組の集合である「ルート」DirectoryContentsオブジェクトの記述を返します。他の場合には、GetDirectoryContents方法のEmbeddedFileProviderは常にNotFoundDirectoryContentsオブジェクトを返します。
[ASP.NETコア3の枠組みシークレット]のファイルシステム[1]:抽象的な"ファイルシステム"
[ASP.NETコア3の枠組みシークレット]のファイルシステム[2]:総合デザイン
[ASP.NETコア3の枠組みシークレット]のファイルシステム[ 3]:物理ファイルシステム
[ASP.NETコア3枠組みシークレット】ファイルシステム[4]:アセンブリ埋め込みファイルシステム