V2.0 エクステンションロード機構
背景
V2.0 では、V1.1 のエクステンションにおける次の問題を解消するため、エクステンションのロード機構を変更しました。
- Next Design 本体が参照するライブラリより新しいバージョンのライブラリをロードできません。そのためエクステンションで 3rd Party が提供する新しいバージョンのライブラリが提供する機能が利用できませんでした。
- 複数のエクステンションで異なるバージョンの同じライブラリをロードできません。そのためインストールするすべてのエクステンションでライブラリのバージョンを揃える必要がありました。
- ネイティブライブラリが含まれるエクステンションがロードできません。そのためネイティブライブラリに依存するエクステンションを配布できませんでした。
エクステンションロード機構の変更点
エクステンション単位で異なるバージョンのライブラリ利用を可能としました
V2.0 では、エクステンション単位で異なる領域にライブラリをロードするように変更しました。
ただし、Next Design 本体が参照するライブラリについては、Next Design 本体が参照するライブラリの方がバージョンが新しい、または、バージョンが同じである場合に限り、エクステンション側で新たにライブラリのロードを行わず、Next Design 本体でロード済みのライブラリを優先します。
これは、以下の理由によります。
- ライブラリロード領域のために確保するメモリサイズを抑制する
- Next Design 本体側の動作を保証する
- Next Design 本体とエクステンション間のデータ交換によるインタフェース不整合を抑制する
変更による効果
- V2.0 のエクステンションでは、Next Design 本体が参照するライブラリより新しいバージョンのライブラリを利用できます。
note
- 例えば、V1.1 のエクステンションでは、Next Design 本体が参照する
Microsoft.WindowsAPICodePack
より新しいバージョンのライブラリを利用できませんでした。 - V2.0 のエクステンションでは、Next Design 本体が参照する
Microsoft.WindowsAPICodePack
より新しいバージョンのライブラリを利用できます。
- V2.0 のエクステンションでは、複数のエクステンションで異なるバージョンの同じライブラリを利用できます。
note
- 例えば、あるエクステンションAが
System.Text.Json
のバージョン4.7.1
を利用している場合、V1.1 では、別のエクステンションBでSystem.Text.Json
の新しいバージョン5.0.2
を利用できませんでした。 - V2.0 では、別のエクステンションBで
System.Text.Json
の新しいバージョン5.0.2
を利用できます。この場合、それぞれ、エクステンションAはバージョン4.7.1
のAPIを、エクステンションBはバージョン5.0.2
のAPIを利用します。
エクステンションの依存ライブラリの解決方法を変更しました
V2.0 では、エクステンションの依存ライブラリの配置場所の解決方法を変更しました。
依存ライブラリの配置場所の解決には、アセンブリメタデータの記述ファイル(*.deps.jsonファイル)を利用します。
また、依存するライブラリがネイティブライブラリの場合であっても正しく認識できるように変更しました。
変更による効果
- アセンブリメタデータの記述により、依存ライブラリの配置構成をエクステンション側でカスタマイズできます。
tip
- 依存ライブラリを NuGet パッケージ管理機能を用いて解決している場合、アセンブリメタデータの記述ファイル(*.deps.jsonファイル)はビルド時に自動生成されます。
- そのため、V2.0 のエクステンションでは、依存ライブラリを NuGet パッケージ管理機能を用いて解決することを推奨します。
- ネイティブライブラリに依存するエクステンションを配布できます。
note
- V1.1 ではエクステンションフォルダ配下にネイティブライブラリを配置したエクステンションはロードできませんでした。
- V2.0 では、アセンブリメタデータを記述することでネイティブライブラリに依存するエクステンションを配置できます。
- また、OS や CPU の違いにより"依存するネイティブライブラリが異なる"場合においても、エクステンションの実行時に解決するため、例えば、
win-x64
向けとwin-x86
向けのネイティブライブラリを1つのエクステンションに同梱できます。
複数のエクステンションから参照されるライブラリにおける静的変数の扱いを変更しました
V2.0 では、エクステンション単位で異なる領域にライブラリをロードするため、静的変数が V1.1 とは異なる扱いとなります。
- V1.1 では、複数のエクステンション間で静的変数が共有されていました。
- V2.0 では、複数のエクステンション間で静的変数が共有されません。そのためエクステンション間での情報の共有に静的変数は利用できません。
note
- 例えば次のようなコードの場合、V1.1 ではすべてのエクステンションでこのクラス変数は共有されます。
- しかし、V2.0 ではエクステンションごとに異なるメモリ管理となるためクラス変数はエクステンション内のみに限定されます。
public class SomeClass
{
private static IDictionary<string, object> _SomeDictionary = new Dictionary<string, object>();
}
エクステンション配布手順の変更点・注意事項
V2.0 のエクステンションのロード機構の変更に伴い、配布するエクステンションの構成も変更となります。
エクステンションフォルダ構成
V2.0 では、エクステンションの配布用フォルダに、マニフェストファイル、エクステンション本体ライブラリ、依存ライブラリに加えて、アセンブリメタデータの記述ファイル(*.deps.jsonファイル)を配置します。
+ ${エクステンションフォルダ}/
- manifest.json
- ${エクステンション本体ライブラリ名}.dll
- ${エクステンション本体ライブラリ名}.deps.json
- ${エクステンション依存ライブラリ}.dll
- ・・・
アセンブリメタデータの記述ファイル
dotnet build でエクステンションをビルドすると、ビルド結果の出力フォルダに自動的に作成されます。詳しくは以下を参照してください。
tip
- エクステンションの配布時には、生成された
*.deps.jsonファイル
をエクステンションフォルダに配置してください。 - 配置されていない場合は、エクステンションが依存するライブラリのロードに失敗する場合があります。
依存ライブラリの収集
dotnet publish でエクステンションの依存ライブラリを出力フォルダに収集できます。詳しくは以下を参照してください。
tip
- dotnet publish は、すべての依存ライブラリが収集されます。
- エクステンションが、Next Design 本体も参照するライブラリを利用する場合、そのライブラリが本体より新しいバージョンでなければ、エクステンション配布時のパッケージから取り除いてパッケージサイズを縮小できます。
国際化対応リソースDLLの配置
DLL方式のエクステンションでは、C# 標準のローカライズが利用できます。
- エクステンション(およびその依存ライブラリ)が文字列リソースを用いた国際化対応を行っている場合、出力フォルダに言語単位のリソース情報を含むライブラリ(*.resources.dll)が生成されます。
- エクステンションの配布時には、それらライブラリをフォルダ構成と共にエクステンションフォルダに配置してください。
+ ${エクステンションフォルダ}/
+ en/
- ${エクステンション本体ライブラリ名}.resources.dll
+ fr/
- ${エクステンション本体ライブラリ名}.resources.dll
- manifest.json
- ${エクステンション本体ライブラリ名}.dll
- ${エクステンション本体ライブラリ名}.deps.json
- ${エクステンション依存ライブラリ}.dll
- ・・・
ネイティブライブラリの配置
V2.0 では、エクステンションにネイティブライブラリを利用できるようになりました。
- エクステンション(およびその依存ライブラリ)がネイティブライブラリに依存する場合、出力フォルダにランタイム環境ごとのネイティブライブラリが出力されます。
- エクステンションの配布時には、それらライブラリをフォルダ構成と共にエクステンションフォルダに配置してください。
+ ${エクステンションフォルダ}/
+ runtimes/
+ win-x64/
- ${ネイティブライブラリ名}.dll
+ win-x86/
- ${ネイティブライブラリ名}.dll
- manifest.json
- ${エクステンション本体ライブラリ名}.dll
- ${エクステンション本体ライブラリ名}.deps.json
- ${エクステンション依存ライブラリ}.dll
- ・・・
制限事項
Next Design 本体が参照するライブラリとの競合
Next Design 本体が参照するライブラリより古いバージョンのライブラリはロードされません。本体が参照する新しいバージョンのライブラリが利用されます。 そのため、エクステンションが、Next Designのexeと同じフォルダにあるアセンブリと同じで古いバージョンのアセンブリを利用するとき、それらのアセンブリ間で下位互換性が保証されていない場合はエクステンションの活性化に失敗、または実行時にエラーとなります。
tip
- 例えば、古い
NextDesign.Core
でビルドされたエクステンションで、新しいNextDesign.Core
では廃止されたインタフェースを参照していた場合、新しい Next Design では、該当インタフェースを解決できないためエラーとなります。
ネイティブライブラリを参照するエクステンションの制約
.NET Coreの制限により、ネイティブライブラリの配置場所を解決できない場合があります。
- NativeLibrary.Load() によってネイティブライブラリのロードが要求された場合、V2.0 の新しいエクステンションロードメカニズムでは解決できません。
- そのため、ネイティブライブラリを上記のメソッドでロードしている場合は該当のライブラリがNativeLibrary.Load()でロードできる場所に配置されている必要があります。
現時点で判明している上記制限に該当するネイティブライブラリ
- EFCoreで利用されているSQLiteのネイティブライブラリ(e_sqlite3.dll)が該当します。
- Next Design V2.0 では上記制限を緩和するため、EFCore 3.1系のネイティブライブラリを同梱しています。
- そのため、EFCore 3.1系以外のバージョンに依存するエクステンションの動作は保証されません。
一時的なアセンブリファイル生成に対する制約
実行時に一時的なアセンブリファイルの生成を必要とする機能をエクステンションで利用した場合、エクステンションロード機構がそれらのアセンブリファイルの格納先を特定できないため、エクステンションが正常に動作しない場合があります。 利用する機能についての開発元からの情報に従って、一時的なアセンブリファイルの生成を回避するような実装方法を選択してください。