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

问题描述

我正在尝试使用System.Reflection.Emit中提供的API在F#中进行编译。当我尝试为当前正在构建的程序集中的类型创建函数(代理)时遇到问题。转换以下Java(Java的略微修改版本)类的示例:

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,ParameterModifier[] modifiers)

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

生成类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 。如果我尝试将其更改为后者,则会触发相同的错误...

解决方法

如果我需要为使用.NET类型的函数生成相同的指令,例如Func ,则上述代码可以完美运行(在这种情况下,类型数组为types = [| typeof<int> ; typeof<int> |])。

TypeBuilder继承自Type,因此,当您要引用要代表该类型的实例时,只需传递该实例即可。换句话说,您想要的数组是types = [| typeBuilder :> System.Type; typeof<int> |]

,

如果数组是这样构建的,则它实际上可以工作:

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...