C# 反射生成和泛型类型
我在C# 反射生成和泛型类型,c#,reflection.emit,C#,Reflection.emit,我在Reflection.Emit和类型管理方面又遇到了一个棘手的时刻 比如说,我有一个名为MyType的类型,它是在动态生成的程序集中定义的。 调用MyType.GetMethods()会导致NotSupportedException,这使我不得不编写自己的包装器和查找表集。但是,当我调用标准泛型类型上的GetMethods()或任何其他内省方法(使用我自己的类型作为泛型参数)时,也会发生同样的情况: Tuple=>工作正常 元组=>异常 我可以从泛型类型定义中获取方法列表: typeof
Reflection.Emit
和类型管理方面又遇到了一个棘手的时刻
比如说,我有一个名为MyType
的类型,它是在动态生成的程序集中定义的。
调用MyType.GetMethods()
会导致NotSupportedException
,这使我不得不编写自己的包装器和查找表集。但是,当我调用标准泛型类型上的GetMethods()
或任何其他内省方法(使用我自己的类型作为泛型参数)时,也会发生同样的情况:
=>工作正常Tuple
=>异常元组
typeof(Tuple我会让您参考文档:
上面说
虽然TypeBuilder是从Type派生的,但Type类中定义的某些抽象方法在TypeBuilder中没有完全实现。这些TypeBuilder方法引发NotSupportedException。可以通过使用Type.GetType或Assembly.GetType检索创建的类型并反映检索到的typ来获得所需的功能e
因此:
如何检测一个类型是否可以安全地调用GetMethods()和类似的方法
如果类型对象是TypeBuilder,或者如果该类型引用的是TypeBuilder的任何类型,那么这样做是不安全的
如果类型不安全,如何获取方法的实际列表及其泛型参数值
我会再次让您参考文档。实际上,将类型发送到程序集中,然后将其从程序集中取出。我在a中得到了答案。TypeBuilder
类有一系列静态重载,它们完全可以完成以下任务:
var genericTuple = typeof(Tuple<,>);
var myTuple = genericTuple.MakeGenericType(typeof(int), myType);
var ctor = TypeBuilder.GetConstructor(myTuple, genericTuple.GetConstructors().First());
请编辑您的问题,以包含一个简短但完整的程序来演示该问题。此外,请提供有关NotSupportedException
的更多详细信息-消息中是否没有任何内容?@JonSkeet,异常只是说“该方法不受支持”或者类似的东西。我正在运行一个俄文版的Windows,所以我不知道确切的消息,但它不包含其他信息。stacktrace只有我的GetMethods()
和System.Reflection.Emit.TypeBuilderInstantiation.GetMethods(BindingFlags bindingAttr)
在它里面。如果您需要那些MethodInfo
s(等),因为您仍然忙于构建类型,那么实际上您必须跟踪原始的MethodBuilder
s(等),以便在方法调用和其他发出的调用中使用。如果您需要MethodInfo
s(等)在您已经调用了CreateType
之后,然后,正如Eric回答的那样,您可以在创建的类型上调用这些方法。@KirkWoll,我正在忙于构建另一个类型。例如,我有类型A
和B
。typeB
有一个使用Tuple
的方法,需要从中获取Tuple.Item1
。我已经检测tuple
变量的类型并调用GetProperties()
在它上面。没有要跟踪的MethodBuilder
,因为我没有定义这个类型,只是通过应用泛型参数来实例化它。@JonSkeet,我添加了一小段代码。检查一个类型是否是TypeBuilder
很容易,但是我如何检查一个类型是否引用了TypeBuilder
?@Impworks:为什么你需要检查一下吗?只需完成所有类型构建,发出程序集,然后开始使用类型。你的更大目标并不清楚,但Eric的建议对我来说似乎是前进的方向。至于将类型发出到程序集中的想法,类型可能是相互依赖的。例如,A
使用列表
和B
使用一个列表
。我不能完全发出这两种类型并用CreateType
@Impworks完成它:为什么需要使用GetMethods()
在定义这些类型时?定义这两个类型,然后发出程序集,然后对它们执行任何您需要的操作。听起来这里有很多上下文您还没有包含在您的问题中。@Impworks:啊,现在我们来讨论一下。Reflection.emit太弱了,无法用于构建真正的编译器。它非常适合小玩具编译sks喜欢在LINQ查询中发出动态调用站点和表达式树,但是对于编译器中遇到的各种问题,您很快就会超出它的能力。请使用CCI,而不是Reflection.Emit。
var genericTuple = typeof(Tuple<,>);
var myTuple = genericTuple.MakeGenericType(typeof(int), myType);
var ctor = TypeBuilder.GetConstructor(myTuple, genericTuple.GetConstructors().First());
var genericGetter = typeof(Tuple<,>).GetProperty("Item1").GetMethod;
var actual = TypeBuilder.GetMethod(myTuple, genericGetter);