Entspricht Klassenladeprogrammen in .NET

Weiß jemand, ob es möglich ist, das Äquivalent eines "Java Custom Class Loader" in .NET zu definieren?

Um einen kleinen Hintergrund zu geben:

Ich bin dabei, eine neue Programmiersprache namens "Liberty" zu entwickeln, die auf die CLR abzielt. Eine der Eigenschaften der Sprache ist die Fähigkeit, "Typkonstruktoren" zu definieren, dh Methoden, die vom Compiler zur Kompilierungszeit ausgeführt werden und Typen als Ausgabe generieren. Sie sind eine Art Verallgemeinerung von Generika (die Sprache enthält normale Generika) und ermöglichen das Schreiben von Code wie diesem (in "Liberty" -Syntax):

var t as tuple<i as int, j as int, k as int>;
t.i = 2;
t.j = 4;
t.k = 5;

Wo "Tupel" wie folgt definiert ist:

public type tuple(params variables as VariableDeclaration[]) as TypeDeclaration
{
   //...
}

In diesem speziellen Beispiel der Typkonstruktortuple bietet etwas Ähnliches wie anonyme Typen in VB und C #.

Im Gegensatz zu anonymen Typen haben "Tupel" Namen und können in öffentlichen Methodensignaturen verwendet werden.

Das bedeutet, dass ich eine Möglichkeit brauche, um den Typ, der letztendlich vom Compiler ausgegeben wird, auf mehrere Assemblys zu verteilen. Zum Beispiel möchte ich

tuple<x as int> definiert in Assembly A als derselbe Typ wietuple<x as int> definiert in Assembly B.

Das Problem dabei ist natürlich, dass Assembly A und Assembly B zu unterschiedlichen Zeiten kompiliert werden, was bedeutet, dass beide ihre eigenen inkompatiblen Versionen des Tupeltyps ausgeben würden.

Ich habe versucht, eine Art "Typlöschung" zu verwenden, damit ich eine gemeinsam genutzte Bibliothek mit einer Reihe von Typen wie diesen habe (dies ist die "Liberty" -Syntax):

class tuple<T>
{
    public Field1 as T;
}

class tuple<T, R>
{
    public Field2 as T;
    public Field2 as R;
}

und leiten Sie dann den Zugriff von den Tupelfeldern i, j und k nach umField1, Field2, undField3.

Dies ist jedoch keine wirklich praktikable Option. Dies würde bedeuten, dass zur Kompilierungszeittuple<x as int> undtuple<y as int> Dies würde zu unterschiedlichen Typen führen, während sie zur Laufzeit als der gleiche Typ behandelt würden. Das würde für Dinge wie Gleichheit und Typenidentität viele Probleme verursachen. Für meinen Geschmack ist das eine zu undichte Abstraktion.

Andere mögliche Optionen wären die Verwendung von "State-Bag-Objekten". Die Verwendung eines Zustandsbeutels würde jedoch den gesamten Zweck der Unterstützung von "Typkonstruktoren" in der Sprache zunichte machen. Die Idee dabei ist, "benutzerdefinierte Spracherweiterungen" zu aktivieren, um beim Kompilieren neue Typen zu generieren, mit denen der Compiler die statische Typprüfung durchführen kann.

In Java könnte dies mit benutzerdefinierten Klassenladeprogrammen erfolgen. Grundsätzlich kann der Code, der Tupeltypen verwendet, ausgegeben werden, ohne den Typ auf der Festplatte zu definieren. Dann könnte ein benutzerdefinierter "Klassenladeprogramm" definiert werden, das den Tupeltyp zur Laufzeit dynamisch generiert. Dies würde eine statische Typprüfung innerhalb des Compilers ermöglichen und die Tupeltypen über Kompilierungsgrenzen hinweg vereinheitlichen.

Leider bietet die CLR keine Unterstützung für das Laden benutzerdefinierter Klassen. Das gesamte Laden in die CLR erfolgt auf Baugruppenebene. Es wäre möglich, für jeden "konstruierten Typ" eine separate Assembly zu definieren, was jedoch sehr schnell zu Leistungsproblemen führen würde (wenn viele Assemblys nur einen Typ enthalten, würden zu viele Ressourcen verbraucht).

Also, was ich wissen möchte, ist:

Ist es möglich, so etwas wie Java Class Loader in .NET zu simulieren, wo ich einen Verweis auf einen nicht vorhandenen Typ in ausgeben und dann zur Laufzeit dynamisch einen Verweis auf diesen Typ generieren kann, bevor der Code ausgeführt wird, den ich verwenden möchte?

HINWEIS:

* Ich kenne die Antwort auf die Frage, die ich unten als Antwort gebe, bereits. Allerdings habe ich ungefähr 3 Tage lang nachgeforscht und ziemlich viel IL gehackt, um eine Lösung zu finden. Ich dachte, es wäre eine gute Idee, dies hier zu dokumentieren, falls jemand anderes auf dasselbe Problem stoßen sollte. *

Antworten auf die Frage(2)

Ihre Antwort auf die Frage