簡體   English   中英

IL到C#的轉換

[英]IL to c# conversion

我正在一個項目,它的測試方式很少,並且最近更改了很多代碼。 特別是,已將代碼從使用一個數據提供程序移植到另一個數據提供程序,並將DataSet替換為DTO。

我現在想盡可能地對此進行測試,但是不能現實地為由許多人在所需時間范圍內所做的所有更改創建測試。

使用Mono.cecil,我能夠編寫一個測試,該測試查找所有數據庫調用和相關的存儲過程名稱,並將c#中定義的參數與數據庫中的參數進行比較。

我想更進一步,並實際調用該方法,即使所有參數均為默認值也是如此。 這樣,盡管DataReader可能沒有任何行,但我可以發現該架構並將其與靜態映射器方法進行比較。

例如

var reader = cmd.ExecuteReader();
var Divisions = (from IDataRecord record in reader.GetRows() 
select RecordMapper.GetDivisionFromRecord(record)).ToList();

其中GetRows()是一個簡單的擴展方法,而GetDivisionFromRecord是靜態方法,看起來像這樣

public static Division GetDivisionFromRecord(record)
{
  return new Division
  {
       Id = record.GetValueOrDefault<long?>("id"),
       Name = record.GetValueOrDefault<string>("name")
  };
}

不幸的是,我不知道如何從IL引用轉換為緩存的靜態委托,再回到映射器類中靜態方法的名稱。 如果可以找到方法名稱,則可以使用Cecil來獲取方法並找到GetValueOrDefault的callvirt操作碼,以便建立數據庫別名和類型的集合。

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又使用了反射,並且可以將CachedAnonymousDelegates視為私有靜態字段。 但是我可以看到如何獲得實際的方法調用。

有什么想法可以解決這個問題嗎?

最后,我使用了ICSharpCode.Decompiler和ICSharpCode.NRefactory的AstBuilder將相關的IL從Mono.cecil轉換回c#,以便可以使用正則表達式來發現映射器。

使用這種方法,我使用所有這些元數據來生成應首先進行的數百項測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM