2010-07-05 40 views
1

使用this solution將匿名類型轉換爲使用reflection.emit的字典。工作正常,直到我從3.5更改爲.Net 4.0。在.Net 4.0中未驗證的DynamicMethod代碼(找到ref'this'pointer ... expected ref'<> f__AnonymousType1`)

現在,我得到了「System.Security.VerificationException:操作可能會破壞運行時。」錯誤。

將匿名加載的動態方法轉換爲託管在動態程序集中的一個,保存它,然後在其上運行peverify.exe以找出錯誤。

GOT:[IL]:錯誤:[DynamicAssemblyExample.dll:MyDynamicType ::的MyMethod] [取捨 等0x0000000D] [發現REF( '這個' PTR) 'MyDynamicType'] [預期REF'<> f__AnonymousType1`3 [System.String,System.Int32,System.Byte]'] stac k上的意外類型。 [IL]:錯誤:[DynamicAssemblyExample.dll:MyDynamicType :: MyMethod] [offs et 0x0000000D]方法不可見。 2個錯誤驗證DynamicAssemblyExample.dll

代碼:

foreach (PropertyInfo property in itemType.GetProperties(attributes).Where(info => info.CanRead)) 
    { 
     // load Dictionary (prepare for call later) 
     methIL.Emit(OpCodes.Ldloc_0); 

     // load key, i.e. name of the property 
     methIL.Emit(OpCodes.Ldstr, property.Name); 

     // load value of property to stack 
     methIL.Emit(OpCodes.Ldarg_0); 
     methIL.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null); 

     // perform boxing if necessary 
     if (property.PropertyType.IsValueType) 
     { 
      methIL.Emit(OpCodes.Box, property.PropertyType); 
     } 

     // stack at this point 
     // 1. string or null (value) 
     // 2. string (key) 
     // 3. dictionary 

     // ready to call dict.Add(key, value) 
     methIL.EmitCall(OpCodes.Callvirt, addMethod, null); 

    } 

有沒有辦法來反引用指針實際財產?或者我必須以某種方式施放它?任何指針?

問候!

回答

0

對不起,夥計們犯了一個錯誤,因爲實際的動態方法創建了一個代理類型,它作用於匿名(或非匿名)類型的實例,Ldarg_0代碼正在尋找一個不存在的東西調試實施。

所以我把它改成了OpCodes.Ldnull。

  var attributes = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy; 
     foreach (PropertyInfo property in itemType.GetProperties(attributes).Where(info => info.CanRead)) 
     { 
      // load Dictionary (prepare for call later) 
      methIL.Emit(OpCodes.Ldloc_0); 

      // load key, i.e. name of the property 
      methIL.Emit(OpCodes.Ldstr, property.Name); 

      // load value of property to stack 
      methIL.Emit(OpCodes.Ldnull); 

      //methIL.Emit(OpCodes.Castclass, itemType); 
      methIL.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null); 

      // perform boxing if necessary 
      if (property.PropertyType.IsValueType) 
      { 
       methIL.Emit(OpCodes.Box, property.PropertyType); 
      } 

      // stack at this point 
      // 1. string or null (value) 
      // 2. string (key) 
      // 3. dictionary 

      // ready to call dict.Add(key, value) 
      methIL.EmitCall(OpCodes.Callvirt, addMethod, null); 

     } 

但是在peverifying之後,我仍然看到一個方法不可見的錯誤。是否通過反射來獲取匿名類型屬性的方法?

0

只是一個建議,你有沒有嘗試重寫發出IL實際寫入字典的代碼 - 即沒有Reflection.Emit?我敢打賭,生成的IL在某些方面不合適,而不是訪問匿名類型的代碼。

+0

是的,我做了一個測試,在沒有反射的情況下做了測試,除了castclass操作碼外,它看起來差不多,它給了我一個想法。 – user365004 2010-07-06 01:16:51

+0

Yaay,問題解決了。我只是不得不提出這個觀點,而且它很有效。 .Net 3.5運行時驗證程序顯然有一些漏洞。謝謝回覆。 – user365004 2010-07-06 05:28:57