使用自定义类型从当前正在构建的程序集中检索委托类型

Retrieving a delegate type using custom types from an assembly that is currently being built

我正在尝试使用 System.Reflection.Emit 中提供的 API 在 F# 中创建一个编译器。当我尝试为当前正在构建的程序集中的类型创建函数(委托)时,我 运行 遇到了问题。翻译以下内容的示例 Java(Java 的略微修改版本)class:

class A extends Object {
    Integer x;
    A (Integer x) {
        super();
        this.x = x;
    }
    Function<A, Integer> fun() {
        return (A a) -> { return a.x; };
    }
}

所以,我需要能够使用 Func 的 System.Type 来生成以下 CIL 指令:

newobj instance void class [mscorlib]System.Func`2<class tst.A,int32>::.ctor(object, native int) 

生成相应指令的代码是:

let deleg = System.Linq.Expressions.Expression.GetDelegateType(types)
let constr = deleg.GetConstructor([|typeof<obj> ; typeof<nativeint>|])
ilGenerator.Emit(OpCodes.Newobj, constr) 

其中 types 是 System.Type 个元素的数组。在 Fun 的情况下,类型数组是 [|typ ; typeof<int>|],其中 typ 声明如下:let typ : System.Type = upcast typeBuilder。但是,这会触发以下错误:

System.NotSupportedException: Specified method is not supported.
at System.Reflection.Emit.TypeBuilderInstantiation.GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
at System.Type.GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)

如果我需要为使用 .NET 类型的函数生成相同的指令,例如 Func,那么上面的代码可以完美运行(在这种情况下类型数组是 types = [| typeof<int> ; typeof<int> |] ).上述解决方案为何不起作用的任何建议或如何检索 TypeBuilder(未完成构建)的 System.Type 的任何其他替代方法都非常受欢迎。

class A 的 typeBuilder 的生成方式是:

let typeBuilder = moduleBuilder.DefineType(typ, TypeAttributes.Public ||| TypeAttributes.Class)
typeBuilder.SetParent(typeof<obj>)
typeBuilder.DefineField("x", typeof<int>, FieldAttributes.Public)
let constrBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, [|typeof<int>|])
let methodBuilder = typeBuilder.DefineMethod("fun", MethodAttributes.Public)
let delegRetType =  System.Linq.Expressions.Expression.GetDelegateType([|typeof<obj> ; typeof<int>|]).GetConstructor([|typeof<obj> ; typeof<nativeint>|]).DeclaringType
methodBuilder.SetReturnType(delegRetType) 
methodBuilder.SetParameters([||])
//buildConstrBody - nothing special
//buildMethodBody - generating the instructions using the methodBuilder .GetILGenerator() - triggering the error described above
typeBuilder.CreateType()

注意 delegRetType 实际上是 Func 而不是 Func。如果我尝试将其更改为后者,则会触发相同的错误...

If I needed to generate the same instruction for a function that uses .NET types, for instance Func<Integer, Integer>, then the above code works perfectly (the types array is types = [| typeof<int> ; typeof<int> |] in this case).

TypeBuilder 继承自 Type,因此当您需要引用该类型时,只需传递表示您正在构建的类型的实例即可。也就是说,你要的数组是types = [| typeBuilder :> System.Type; typeof<int> |]

如果数组是这样构建的,它实际上是有效的:

types = [| typeBuilder.GetType(); typeof<int> |]