从当前正在生成的程序集中检索使用GenericTypeParameterBuilder类型的函数委托类型

问题描述

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

class A extends Object {
    A () {}
    Function<A,A> fun() {
        return (A a) -> { return a; }; // OK
    }
}
class B<X extends Object> extends Object {
    X val;
    B (X val) { this.val = val; }
    Function<X,X> fun() {
        return (X x) -> { return x; }; // does not work to translate
    }
}

因此,我需要能够使用Func 和Func 的System.Type,以便生成以下CIL指令(以及一些使用相同Func类型的类似指令) :

callvirt instance !1 class [mscorlib]System.Func`2<class A,class A>::Invoke(!0)
callvirt instance !1 class [mscorlib]System.Func`2<!X,!X>::Invoke(!0)

生成相应指令的代码为:

let deleg = System.Linq.Expressions.Expression.GetFuncType(types)
let method = deleg.GetConstructor([|typeof<obj> ; typeof<nativeint>|]).DeclaringType.GetMethod("Invoke")
ilGenerator.Emit(OpCodes.Callvirt,method)

其中types是System.Type元素的数组。对于Func ,类型数组为[|typeBuilder.GetType() ; typeBuilder.GetType()|],但是对于类B中的Func 来说,这是不起作用的,就像对{{1}使用[|genericTypeParameterBuilder.GetType() ; genericTypeParameterBuilder.GetType()|] }数组会生成一条奇怪的CIL指令(程序集仍在构建中,但是指令错误):

types

生成类A的typeBuilder的方式是:

callvirt instance !1 class [mscorlib]System.Func`2<class [mscorlib]System.Reflection.Emit.GenericTypeParameterBuilder,class [mscorlib]System.Reflection.Emit.GenericTypeParameterBuilder>::Invoke(!0)

类型B也会发生这种情况,多余的let typeBuilder = moduleBuilder.DefineType(typ,TypeAttributes.Public ||| TypeAttributes.Class) typeBuilder.SetParent(typeof<obj>) let constrBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard,[||]) let methodBuilder = typeBuilder.DefineMethod("fun",MethodAttributes.Public) let delegRetType = System.Linq.Expressions.Expression.GetDelegateType([|typeof<obj> ; typeof<int>|]).GetConstructor([|typeBuilder.GetType() ; typeBuilder.GetType()|]).DeclaringType methodBuilder.SetReturnType(delegRetType) methodBuilder.SetParameters([||]) //buildConstrBody - nothing special //buildMethodBody - generating the instructions using the methodBuilder .GetILGenerator() - using various System.Func types typeBuilder.CreateType() 的构造是这样的,没有修饰符或限制:

genericTypeParameterBuilder

我构建类型数组的方式是使用以下函数:

let genericTypeParameterBuilder = typeBuilder.DefineGenericParameters([|"X"|]).[0]

控制台:

let rec typesForFuncRec (types: System.Type list) : System.Type list = 
    match types with
        | [] -> []
        | typ :: rest -> 
            match typ with
                | :? GenericTypeParameterBuilder as gtpb ->     
                    printfn "generic GetType()            : %O" (gtpb.GetType())
                    printfn "generic :>                   : %O" (gtpb :> System.Type)
                    printfn "generic ReflectedType        : %O" (gtpb.ReflectedType)
                    printfn "generic UnderlyingSystemType : %O" (gtpb.UnderlyingSystemType)
                    printfn "generic MakeByRefType()      : %O" (gtpb.MakeByRefType())  
                    gtpb.GetType() :: (typesForFuncRec rest)
                | :? TypeBuilder as tb -> tb.GetType() :: (typesForFuncRec rest)
                | _ -> typ :: (typesForFuncRec rest)
;;

我还尝试使用generic GetType() : System.Reflection.Emit.GenericTypeParameterBuilder generic :> : X generic ReflectedType : B[X] generic UnderlyingSystemType : X generic MakeByRefType() : X& gtpb.GetType()来代替gtpb :> System.Type,它们会引发以下错误:

gtpb.UnderlyingSystemType

我也尝试过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) ,它会引发以下错误:

gtpb.MakeByRefType()

问题是:

  1. 如何获取泛型类型参数的System.Func类型?我已经尝试了几个小时,它开始让我发疯。

  2. (不那么重要,我只是好奇)对于常规类类型生成器的System.Func,为什么我需要在其他操作中将System.Type检索为System.ArgumentException: type must not be ByRef at System.Linq.Expressions.Expression.GetFuncType(Type[] typeArgs) (方法返回类型/参数类型),我只能使用强制转换:typeBuilder.GetType() ??

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

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