如何使用mono.cecil按类型在方法体中查找变量?

时间:2013-01-03 18:58:30

标签: c# mono.cecil

我在这里看过cecil的问题,我没有看到有关这个特定问题的任何内容。

我想要实现的是在method.Body.Variables中找到某个类型的变量(在我的情况下为System.Exception

我编写了以下代码,认为它可以解决问题:

var exceptionTypeReference = module.Import(typeof(Exception));
var exceptionVariable = method.Body.Variables.First(x => x.VariableType == exceptioinTypeReference);

即使我确定原因是我与cecil的无关,我觉得奇怪的是我在运行时遇到“序列包含无匹配元素”错误。

我已经完成了代码,我知道那里有一个变量,它的类型是System.Exception,但它不想与exceptionTypeReference匹配。

我确信这很简单,而且我的大脑因学习塞西尔而大吃一惊。即便如此,任何指针,用湿鱼等砸在脸上,都会非常感激。

1 个答案:

答案 0 :(得分:4)

每次导入类型时,它都是TypeReference

的不同实例

所以这个

var typeReference1 = moduleDefinition.Import(typeof (Exception));
var typeReference2 = moduleDefinition.Import(typeof (Exception));
Debug.WriteLine(typeReference1 == typeReference2);

将输出false

所以当你进行查询时

  • VariableType可能是代表TypeReference
  • Exception的实例
  • exceptionTypeReference将是代表TypeReference
  • Exception的实例

但它们不是同一个引用,并且TypeReference没有内置的等式检查。

您需要做的是

var exceptionType = module.Import(typeof(Exception));
var exceptionVariable = method
              .Body
              .Variables
              .First(x => x.VariableType.FullName == exceptionType.FullName);

还记得你必须处理继承的异常类型。

作为一方,不要小心使用.Import(typeof (Exception))。原因是它为您提供了当前代码的Exception类型,而不是目标程序集的Exception类型。例如,您可以使用.net4程序集处理WinRT程序集。导入.net4异常类型可能会给你一些奇怪的行为。

所以你这样做是安全的

var exceptionVariable = method
                   .Body
                   .Variables
                   .First(x => x.VariableType.FullName == "System.Exception");