问题描述
我正在尝试使用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
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 [|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()
问题是:
-
如何获取泛型类型参数的System.Func类型?我已经尝试了几个小时,它开始让我发疯。
-
(不那么重要,我只是好奇)对于常规类类型生成器的System.Func,为什么我需要在其他操作中将System.Type检索为
System.ArgumentException: type must not be ByRef at System.Linq.Expressions.Expression.GetFuncType(Type[] typeArgs)
(方法返回类型/参数类型),我只能使用强制转换:typeBuilder.GetType()
??
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)