C# IL-c转换

C# IL-c转换,c#,reflection,delegates,il,mono.cecil,C#,Reflection,Delegates,Il,Mono.cecil,我正在从事一个项目,该项目在测试方面几乎没有什么进展,而且最近有大量代码被修改。特别是,代码已经从一个数据提供程序移植到另一个数据提供程序,数据集已经被DTO替换 我现在想尽可能多地测试这一点,但不能实际地为许多人在要求的时间范围内所做的所有更改创建测试 使用Mono.cecil,我能够编写一个测试,找到所有数据库调用和相关存储过程名称,并将c中定义的参数与数据库中的参数进行比较 我想更进一步,实际调用该方法,即使所有参数都是默认值。通过这种方式,尽管DataReader可能没有任何行,但我可以

我正在从事一个项目,该项目在测试方面几乎没有什么进展,而且最近有大量代码被修改。特别是,代码已经从一个数据提供程序移植到另一个数据提供程序,数据集已经被DTO替换

我现在想尽可能多地测试这一点,但不能实际地为许多人在要求的时间范围内所做的所有更改创建测试

使用Mono.cecil,我能够编写一个测试,找到所有数据库调用和相关存储过程名称,并将c中定义的参数与数据库中的参数进行比较

我想更进一步,实际调用该方法,即使所有参数都是默认值。通过这种方式,尽管DataReader可能没有任何行,但我可以发现模式并尝试将其与静态映射器方法进行比较

乙二醇

其中GetRows是一个简单的扩展方法,GetDivisionFromRecord是一个静态方法,看起来有点像这样

public static Division GetDivisionFromRecord(record)
{
  return new Division
  {
       Id = record.GetValueOrDefault<long?>("id"),
       Name = record.GetValueOrDefault<string>("name")
  };
}
不幸的是,我不知道如何从IL引用到缓存的静态委托转换回mapper类中静态方法的名称。 如果我能找到方法名,那么我就可以使用Cecil来获取该方法,并找到callvirt操作码来获取ValuerDefault,这样我就可以构建一个数据库别名和类型的集合

IL看起来像这样

IL_0025: callvirt instance class [System.Data]System.Data.IDataReader IOracleHelper::ExecuteReader(class OracleCommandWrapper)
IL_002a: stloc.0
IL_002b: ldloc.0
IL_002c: call class [mscorlib]System.Collections.Generic.IEnumerable`1<class [System.Data]System.Data.IDataRecord> NullSafeExtensions::GetRows(class [System.Data]System.Data.IDataReader)
IL_0031: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Cast<class [System.Data]System.Data.IDataRecord>(class [mscorlib]System.Collections.IEnumerable)
IL_0036: ldsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_003b: brtrue.s IL_0050
IL_003d: ldnull
IL_003e: ldftn class [Services.Common]Division DataDao::'<GetAlDivisions>b__16'(class [System.Data]System.Data.IDataRecord)
IL_0044: newobj instance void class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division>::.ctor(object, native int)
IL_0049: stsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_004e: br.s IL_0050
IL_0050: ldsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_0055: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!1> [System.Core]System.Linq.Enumerable::Select<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [System.Core]System.Func`2<!!0, !!1>)
IL_005a: call class [mscorlib]System.Collections.Generic.List`1<!!0> [System.Core]System.Linq.Enumerable::ToList<class [Services.Common]Division>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
我使用了cecil和reflection,可以将CachedAnonymousDelegate视为私有静态字段。但我可以看到如何获得实际的方法调用


你知道我该怎么办吗

最后,我使用ICSharpCode.Decompiler中的AstBuilder和ICSharpCode.nFactory将相关IL从Mono.cecil转换回c,这样我就可以使用正则表达式来发现映射器


使用这种方法,我使用所有这些元数据来生成数百个测试,这些测试本来应该首先完成。

最后,我使用ICSharpCode.Decompiler和ICSharpCode.nFactory中的AstBuilder将相关IL从Mono.cecil转换回c,这样我就可以使用正则表达式来发现映射器


使用这种方法,我使用所有这些元数据来生成数百个测试,这些测试本来应该首先完成。

Telerik提供了一个免费的反编译器,如果您只想反编译.NET程序集。这可能会为你节省一些时间。它仍然是自由的,不像反射器。我和Telerk没有任何联系,所以没有关系要透露。这是一种奇怪的方式。只需在源代码管理中的版本上运行一个diff,以了解您应该测试什么。我已经在使用一个反编译器mono.cecil。我不想使用Reflector/ILSpy等工具,因为这样整个测试过程都是手动的,我不会有一个可以用于回归测试和验证任何数据库版本等的测试用例。如果您只想反编译.NET程序集,Telerik提供了一个免费的反编译程序。这可能会为你节省一些时间。它仍然是自由的,不像反射器。我和Telerk没有任何联系,所以没有关系要透露。这是一种奇怪的方式。只需在源代码管理中的版本上运行一个diff,以了解您应该测试什么。我已经在使用一个反编译器mono.cecil。我不想使用诸如Reflector/ILSpy等工具,因为这样整个测试过程都是手动的,我不会有一个可以用于回归测试和验证任何数据库版本等的测试用例。。。
IL_0025: callvirt instance class [System.Data]System.Data.IDataReader IOracleHelper::ExecuteReader(class OracleCommandWrapper)
IL_002a: stloc.0
IL_002b: ldloc.0
IL_002c: call class [mscorlib]System.Collections.Generic.IEnumerable`1<class [System.Data]System.Data.IDataRecord> NullSafeExtensions::GetRows(class [System.Data]System.Data.IDataReader)
IL_0031: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Cast<class [System.Data]System.Data.IDataRecord>(class [mscorlib]System.Collections.IEnumerable)
IL_0036: ldsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_003b: brtrue.s IL_0050
IL_003d: ldnull
IL_003e: ldftn class [Services.Common]Division DataDao::'<GetAlDivisions>b__16'(class [System.Data]System.Data.IDataRecord)
IL_0044: newobj instance void class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division>::.ctor(object, native int)
IL_0049: stsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_004e: br.s IL_0050
IL_0050: ldsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_0055: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!1> [System.Core]System.Linq.Enumerable::Select<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [System.Core]System.Func`2<!!0, !!1>)
IL_005a: call class [mscorlib]System.Collections.Generic.List`1<!!0> [System.Core]System.Linq.Enumerable::ToList<class [Services.Common]Division>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)