Эквивалент загрузчиков классов в .NET

Кто-нибудь знает, возможно ли определить эквивалент «загрузчика пользовательских классов Java» в .NET?

Чтобы дать немного фона:

Я нахожусь в процессе разработки нового языка программирования, предназначенного для CLR, под названием «Свобода». Одной из особенностей языка является его способность определять «конструкторы типов», которые представляют собой методы, которые выполняются компилятором во время компиляции и генерируют типы в качестве вывода. Они являются своего рода обобщением обобщений (в языке действительно есть обычные обозначения) и позволяют писать такой код (в синтаксисе «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> определено в сборке 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 выполняется на уровне сборки. Можно было бы определить отдельную сборку для каждого «составного типа», но это очень быстро привело бы к проблемам с производительностью (наличие множества сборок с одним типом в них потребовало бы слишком много ресурсов).

Итак, что я хочу знать:

Можно ли имитировать что-то наподобие Java Class Loaders в .NET, где я могу выдать ссылку на несуществующий тип в, а затем динамически сгенерировать ссылку на этот тип во время выполнения до того, как код должен будет его использовать?

НОТА:

* Я на самом деле уже знаю ответ на вопрос, который я предоставляю в качестве ответа ниже. Тем не менее, мне потребовалось около 3 дней исследований и немало хакерских атак, чтобы найти решение. Я подумал, что было бы неплохо документировать это здесь, если кто-то столкнется с той же проблемой. *

Ответы на вопрос(2)

Ваш ответ на вопрос