¿Alguien sabe si es posible definir el equivalente de un "cargador de clases personalizado de Java" en .NET?Equivalente de cargadores de clase en .NET
Para dar un poco de historia:
estoy en el proceso de desarrollar un nuevo lenguaje de programación que se dirige el CLR, llamado "Libertad". Una de las características del lenguaje es su capacidad para definir "constructores de tipo", que son métodos que el compilador ejecuta en tiempo de compilación y genera tipos como salida. Son una especie de generalización de los genéricos (el lenguaje tiene genéricos normales en ella), y permitir que un código como el que se escribirá (en "libertad" sintaxis):
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 como tal :
public type tuple(params variables as VariableDeclaration[]) as TypeDeclaration
{
//...
}
en este ejemplo particular, el constructor de tipo tuple
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 se pueden usar dentro de las firmas de métodos públicos.
Esto significa que necesito una forma para que el tipo que finalmente termine siendo emitido por el compilador se pueda compartir en varios ensambles. Por ejemplo, quiero
tuple<x as int>
se define en la Asamblea de A a llegar a ser del mismo tipo que se define en la Asamblea tuple<x as int>
B.
El problema con esto, por supuesto, es que la Asamblea A y B de la Asamblea van a compilarse en diferentes momentos, lo que significa que ambos terminarían emitiendo sus propias versiones incompatibles del tipo de tupla.
Miré en el uso de algún tipo de "tipo borrado" de hacer esto, por lo que tendría una biblioteca compartida con un montón de tipos como este (esta es la sintaxis "Libertad"):
class tuple<T>
{
public Field1 as T;
}
class tuple<T, R>
{
public Field2 as T;
public Field2 as R;
}
y luego simplemente redirigir el acceso desde los campos tuple i, j y k al Field1
, Field2
y Field3
.
Sin embargo, esa no es realmente una opción viable. Esto significaría que en el tiempo de compilación tuple<x as int>
y tuple<y as int>
terminarían siendo tipos diferentes, mientras que en tiempo de ejecución serían tratados del mismo tipo. Eso causaría muchos problemas para cosas como igualdad y tipo de identidad. Eso es demasiado agujereado como una abstracción para mis gustos.
Otras opciones posibles serían utilizar "objetos de bolsa de estado". Sin embargo, usar una bolsa de estado vencería 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 tiempo de compilación con los que el compilador pueda realizar la comprobación de tipos estáticos.
En Java, esto se puede hacer utilizando cargadores de clases personalizados. Básicamente, el código que usa tipos de tuplas podría emitirse sin definir realmente el tipo en el disco. Entonces se podría definir un "cargador de clases" personalizado que genere dinámicamente el tipo de tupla en el tiempo de ejecución. Eso permitiría la comprobación del tipo estático dentro del compilador, y unificaría los tipos de tupla a través de los límites de compilación.
Desafortunadamente, sin embargo, el CLR no proporciona soporte para la carga personalizada de clases.Toda la carga en el CLR se realiza en el nivel de ensamblaje. Sería posible definir un ensamblaje separado para cada "tipo construido", pero eso llevaría muy rápidamente a problemas de rendimiento (tener muchos ensambles con solo un tipo en ellos usaría demasiados recursos).
Por lo tanto, lo que yo quiero saber es:
¿Es posible simular algo parecido a Java Clase Cargadores 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 usarlo?
NOTA:
* En realidad, ya sé la respuesta a la pregunta, que proporciono como una respuesta a continuación. Sin embargo, me tomó alrededor de 3 días de investigación, y un poco de pirateo IL para 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. *
Oh wow, primera publicación que alguna vez pensé que debería tener títulos de capítulo. Gran información! ¡Gracias por publicar! –