使用自定义类型从当前正在构建的程序集中检索委托类型
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
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> |]
我正在尝试使用 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 类型的函数生成相同的指令,例如 Functypes = [| 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
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> |]