有谁知道是否可以在.NET 中定义等效于“java 自定义类加载器”的内容?
提供一点背景:
我正在开发一种针对 CLR 的新编程语言,称为“Liberty”。该语言的特点之一是它能够定义“类型构造函数”,这是由编译器在编译时执行并生成类型作为输出的方法。它们是泛型的一种概括(该语言中确实有普通的泛型),并允许编写这样的代码(以“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>
在程序集 A 中定义的类型最终与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 中的所有加载都是在程序集级别完成的。可以为每个“构造类型”定义一个单独的程序集,但这会很快导致性能问题(有许多只有一种类型的程序集会使用太多资源)。
所以,我想知道的是:
是否可以在 .NET 中模拟 Java 类加载器之类的东西,我可以在其中发出对不存在类型的引用,然后在需要使用它的代码运行之前在运行时动态生成对该类型的引用?
笔记:
*我实际上已经知道这个问题的答案,我在下面提供了答案。然而,我花了大约 3 天的时间进行研究,并进行了大量的 IL 黑客攻击,以便提出解决方案。我认为在这里记录它是一个好主意,以防其他人遇到同样的问题。*