.NET で「Java カスタム クラス ローダー」に相当するものを定義できるかどうかは誰にもわかりませんか?
少し背景を説明するには:
「Liberty」と呼ばれる、CLR を対象とする新しいプログラミング言語を開発中です。この言語の機能の 1 つは、「型コンストラクター」を定義する機能です。これは、コンパイル時にコンパイラーによって実行され、出力として型を生成するメソッドです。それらはジェネリックの一種の一般化であり (言語には通常のジェネリックが含まれています)、次のようなコードを ("Liberty" 構文で) 記述できます。
var t as tuple<i as int, j as int, k as int>;
t.i = 2;
t.j = 4;
t.k = 5;
「タプル」は次のように定義されています。
public type tuple(params variables as VariableDeclaration[]) as TypeDeclaration
{
//...
}
この特定の例では、型コンストラクターtuple
は、VB および C# の匿名型に似たものを提供します。
ただし、匿名型とは異なり、「タプル」には名前があり、パブリック メソッド シグネチャ内で使用できます。
これは、最終的にコンパイラによって出力される型を複数のアセンブリ間で共有できるようにする方法が必要であることを意味します。たとえば、私はしたいです
tuple<x as int>
tuple<x as int>
アセンブリ A で定義され、最終的にアセンブリ B で定義されたものと同じ型になります。
もちろん、これの問題は、アセンブリ A とアセンブリ B が異なる時間にコンパイルされることです。つまり、どちらも、タプル型の互換性のない独自のバージョンを発行することになります。
これを行うためにある種の「型消去」を使用することを検討したため、次のような型の束を持つ共有ライブラリが作成されます (これは「Liberty」構文です)。
class tuple<T>
{
public Field1 as T;
}
class tuple<T, R>
{
public Field2 as T;
public Field2 as R;
}
次に、i、j、および k タプル フィールドからのアクセスを 、 、および にリダイレクトField1
しField2
ますField3
。
ただし、それは実際には実行可能なオプションではありません。これは、コンパイル時tuple<x as int>
にtuple<y as int>
は と が異なる型になることを意味しますが、実行時には同じ型として扱われます。これは、等価性や型の同一性などに多くの問題を引き起こします。それは私の好みにはあまりにも抽象的すぎます。
他の可能なオプションは、「ステート バッグ オブジェクト」を使用することです。ただし、状態バッグを使用すると、言語で「型コンストラクター」をサポートするという目的全体が無効になります。「カスタム言語拡張機能」を有効にして、コンパイラが静的な型チェックを実行できるコンパイル時に新しい型を生成できるようにするという考え方があります。
Java では、カスタム クラス ローダーを使用してこれを行うことができます。基本的に、タプル型を使用するコードは、実際にディスク上で型を定義しなくても発行できます。次に、実行時にタプル型を動的に生成するカスタム「クラス ローダー」を定義できます。これにより、コンパイラ内で静的な型チェックが可能になり、コンパイルの境界を越えてタプル型が統一されます。
ただし、残念ながら、CLR はカスタム クラスの読み込みをサポートしていません。CLR でのすべての読み込みは、アセンブリ レベルで行われます。「構築された型」ごとに個別のアセンブリを定義することは可能ですが、それはすぐにパフォーマンスの問題につながります (型が 1 つしかないアセンブリが多数あると、リソースが多すぎます)。
だから、私が知りたいのは:
.NET で Java クラス ローダーのようなものをシミュレートして、存在しない型への参照を発行し、それを使用する必要があるコードを実行する前に、実行時にその型への参照を動的に生成することはできますか?
ノート:
*実際には、質問への回答は既に知っています。以下に回答として提供します。ただし、解決策を見つけるために、約 3 日間の調査と、かなりの IL ハッキングが必要でした。他の誰かが同じ問題に遭遇した場合に備えて、ここに文書化することをお勧めします. *