在什么情况下TypeBuilder.CreateType调用AppDomain.OnTypeResolveEvent?

时间:2016-06-12 00:49:22

标签: c# reflection.emit

根据the documentation of System.Reflection.Emit.TypeBuilder.CreateType

  

如果封闭类型包含定义为嵌套类型的值类型的字段(例如,定义为嵌套类型的枚举字段),则在封闭类型上调用CreateType方法将生成AppDomain。 TypeResolve事件。

我正在尝试调试一个在完全不同的(并且完全没有记录的!)情况下引发此事件的编译器:我有一个接口(不能包含字段或嵌套类型),并且其中一个接口上的方法有一个泛型参数,上面有一个特定类型的约束。 TypeResolve正在询问该约束的类型。

调试器说调用堆栈如下所示:

System.AppDomain.OnTypeResolveEvent
System.Reflection.Emit.TypeBuilder.CreateTypeNoLock
System.Reflection.Emit.TypeBuilder.CreateType
My.Compiler.TypeCreator.HandleTypeCreation

但调试器的TypeBuilder.CreateTypeNoLockthe reference source反编译都没有显示此调用发生的位置。实际上,在参考源文件中搜索" TypeResolve"什么都不产生,这意味着什么"魔术"正在继续。

我在哪里可以找到提升此TypeResolve事件的实际逻辑,以便我可以修复编译器实现来处理它?<​​/ p>

1 个答案:

答案 0 :(得分:1)

查看文档中的AppDomain.TypeResolve Event。 在评论中,它说:

  

当公共语言运行库无法确定可以创建所请求类型的程序集时,会发生TypeResolve事件。

OnTypeResolveEvent Method in the Referencesource上是这条评论:

  

//此方法由VM调用

当您使用msdn条目中的示例并在OnTypeResolveEvent方法上放置断点时,您将获得如下的堆栈跟踪:

mscorlib.dll!System.AppDomain.OnTypeResolveEvent(System.Reflection.RuntimeAssembly assembly, string typeName)
[Native to Managed Transition]  
[Managed to Native Transition]  
mscorlib.dll!System.RuntimeTypeHandle.GetTypeByName(string name, bool throwOnError, bool ignoreCase, bool reflectionOnly, ref System.Threading.StackCrawlMark stackMark, System.IntPtr pPrivHostBinder, bool loadTypeFromPartialName)
mscorlib.dll!System.RuntimeType.GetType(string typeName, bool throwOnError, bool ignoreCase, bool reflectionOnly, ref System.Threading.StackCrawlMark stackMark)
mscorlib.dll!System.Type.GetType(string typeName, bool throwOnError)
ResolveTest.exe!Test.Main()

所以我认为非常清楚这个事件将由运行时本身调用,而不是由框架库中的一个特定函数调用。

要处理这种情况,将自己的委托放在AppDomain.TypeResolve事件上就足够了,并通过提供缺少的类型来帮助运行时。