Equivalente de cargadores de clase en .NET

¿Alguien sabe si es posible definir el equivalente de un "cargador de clases personalizado de Java" en .NET?

Para dar un poco de historia:

Estoy en el proceso de desarrollar un nuevo lenguaje de programación que apunta al CLR, llamado "Liberty". Una de las características del lenguaje es su capacidad para definir "constructores de tipos", que son métodos que ejecuta el compilador en el momento de la compilación y generan tipos como salida. Son una especie de generalización de genéricos (el lenguaje sí tiene genéricos normales), y permiten escribir código como este (en la sintaxis de "Liberty"):

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

Donde "tupla" se define así:

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

En este ejemplo particular, el constructor de tipotuple&nbsp;proporciona algo similar a los tipos anónimos en VB y C #.

Sin embargo, a diferencia de los tipos anónimos, las "tuplas" tienen nombres y pueden usarse dentro de firmas de métodos públicos.

Esto significa que necesito una forma para que el compilador que finalmente termina siendo emitido por el compilador se pueda compartir en varios ensamblajes. Por ejemplo, quiero

tuple<x as int>&nbsp;definido en la Asamblea A para terminar siendo el mismo tipo quetuple<x as int>&nbsp;definido en la Asamblea B.

El problema con esto, por supuesto, es que la Asamblea A y la Asamblea B se compilarán en diferentes momentos, lo que significa que ambos terminarán emitiendo sus propias versiones incompatibles del tipo de tupla.

Busqué usar una especie de "borrado de tipo" para hacer esto, de modo que tuviera una biblioteca compartida con un montón de tipos como este (esta es la sintaxis de "Liberty"):

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

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

y luego simplemente redireccione el acceso desde los campos de tupla i, j y k aField1, Field2yField3.

Sin embargo, esa no es realmente una opción viable. Esto significaría que en tiempo de compilacióntuple<x as int>&nbsp;ytuple<y as int>&nbsp;terminarían siendo tipos diferentes, mientras que en tiempo de ejecución se tratarían como el mismo tipo. Eso causaría muchos problemas para cosas como la igualdad y la identidad de tipo. Eso es demasiado escurridizo de una abstracción para mi gusto.

Otras opciones posibles serían usar "objetos de bolsa de estado". Sin embargo, usar una bolsa de estado anularía todo el propósito de tener soporte para "constructores de tipo" en el idioma. La idea es habilitar "extensiones de lenguaje personalizadas" para generar nuevos tipos en el momento de la compilación con los que el compilador puede realizar la comprobación de tipos estáticos.

En Java, esto podría hacerse usando cargadores de clases personalizados. Básicamente, el código que utiliza los tipos de tuplas podría emitirse sin definir realmente el tipo en el disco. Luego se podría definir un "cargador de clases" personalizado que generaría dinámicamente el tipo de tupla en tiempo de ejecución. Eso permitiría la verificación de tipos estáticos dentro del compilador y unificaría los tipos de tuplas a través de los límites de compilación.

Desafortunadamente, sin embargo, el CLR no proporciona soporte para la carga de clases personalizada. Toda la carga en el CLR se realiza en el nivel de montaje. Sería posible definir un conjunto separado para cada "tipo construido", pero eso conduciría muy rápidamente a problemas de rendimiento (tener muchos conjuntos con solo un tipo en ellos utilizaría demasiados recursos).

Entonces, lo que quiero saber es:

¿Es posible simular algo como Java Class Loaders en .NET, donde puedo emitir una referencia a un tipo no existente y luego generar dinámicamente una referencia a ese tipo en tiempo de ejecución antes de que se ejecute el código que necesita usar?

NOTA:

* En realidad, ya conozco la respuesta a la pregunta, que proporciono como respuesta a continuación. Sin embargo, me tomó cerca de 3 días de investigación y un poco de pirateo de IL para poder encontrar una solución. Pensé que sería una buena idea documentarlo aquí en caso de que alguien más se encontrara con el mismo problema. *