Odpowiednik klas ładujących w .NET

Czy ktoś wie, czy można zdefiniować odpowiednik „java custom class loader” w .NET?

Aby dać trochę tła:

Jestem w trakcie opracowywania nowego języka programowania skierowanego do CLR, zwanego „Liberty”. Jedną z cech języka jest jego zdolność do definiowania „konstruktorów typów”, które są metodami wykonywanymi przez kompilator w czasie kompilacji i generują typy jako dane wyjściowe. Są one swego rodzaju uogólnieniem generycznych (język ma w sobie normalne generics) i pozwalają na napisanie kodu takiego jak ten (w składni „Liberty”):

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

Gdzie „krotka” jest zdefiniowana tak:

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

W tym konkretnym przykładzie konstruktor typutuple zapewnia coś podobnego do anonimowych typów w VB i C #.

Jednak w przeciwieństwie do typów anonimowych, „krotki” mają nazwy i mogą być używane wewnątrz publicznych podpisów metod.

Oznacza to, że potrzebuję sposobu na typ, który ostatecznie zostanie wyemitowany przez kompilator, aby mógł być współdzielony przez wiele zespołów. Na przykład chcę

tuple<x as int> zdefiniowane w Zgromadzeniu A, aby być tym samym typem cotuple<x as int> zdefiniowane w Zgromadzeniu B.

Problem z tym oczywiście polega na tym, że Assembly A i Assembly B będą kompilowane w różnym czasie, co oznacza, że ​​oba będą emitować własne, niekompatybilne wersje typu krotki.

Aby to zrobić, zajrzałem do jakiegoś rodzaju „wymazywania typu”, aby mieć bibliotekę współdzieloną z kilkoma typami takimi jak ten (jest to składnia „Liberty”):

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

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

a następnie po prostu przekierowuj dostęp z pól krotki i, j oraz k doField1, Field2, iField3.

Nie jest to jednak realna opcja. Oznaczałoby to, że w czasie kompilacjituple<x as int> ituple<y as int> skończyłyby się różnymi typami, podczas gdy w czasie wykonywania byłyby traktowane jako ten sam typ. Spowodowałoby to wiele problemów dla rzeczy takich jak równość i tożsamość typu. To jest zbyt nieszczelne dla abstrakcji dla moich gustów.

Innymi możliwymi opcjami byłoby użycie „obiektów worków państwowych”. Jednak użycie worka stanu pokonałoby cały cel posiadania obsługi „konstruktorów typów” w języku. Pomysł polega na włączeniu „niestandardowych rozszerzeń językowych” w celu wygenerowania nowych typów w czasie kompilacji, które kompilator może wykonywać za pomocą statycznego sprawdzania typów.

W Javie można to zrobić za pomocą niestandardowych programów ładujących klasy. Zasadniczo kod, który używa typów krotek, może być emitowany bez faktycznego definiowania typu na dysku. Następnie można zdefiniować niestandardowy „program ładujący klasy”, który dynamicznie generowałby typ krotki w czasie wykonywania. Pozwoliłoby to na sprawdzenie statycznego typu wewnątrz kompilatora i ujednoliciłoby typy krotek w granicach kompilacji.

Niestety, CLR nie zapewnia obsługi niestandardowego ładowania klas. Całe ładowanie w CLR odbywa się na poziomie zespołu. Możliwe byłoby zdefiniowanie oddzielnego zespołu dla każdego „skonstruowanego typu”, ale to bardzo szybko doprowadziłoby do problemów z wydajnością (posiadanie wielu zestawów z tylko jednym typem wymagałoby użycia zbyt wielu zasobów).

Więc chcę wiedzieć:

Czy możliwe jest zasymulowanie czegoś takiego jak Java Class Loaders w .NET, gdzie mogę wyemitować odwołanie do nieistniejącego typu, a następnie dynamicznie wygenerować odwołanie do tego typu w czasie wykonywania przed uruchomieniem kodu, aby go użyć?

UWAGA:

* Właściwie już znam odpowiedź na pytanie, które podaję jako odpowiedź poniżej. Jednak zajęło mi to około 3 dni badań i sporo hackowania IL w celu znalezienia rozwiązania. Doszedłem do wniosku, że dobrym pomysłem byłoby udokumentowanie tego tutaj, na wypadek gdyby ktoś inny napotkał ten sam problem. *

questionAnswers(2)

yourAnswerToTheQuestion