2011-05-12 52 views
0

我有一個動態方法,它需要一個DataRecord並將數據映射到某個類型的對象。C#IL代碼將值添加到詞典

DynamicMethod_ILGenerator

來源的對象具有Dictionary<string,object>類型的詞典中,不能結合的DataRecord保存任何屬性。

但是,我似乎無法解決如何將這些添加到詞典。

我知道我必須在字典上撥打Emit(OpCodes.Callvirt, addMethod),但無論我嘗試什麼,我都無法弄清楚如何讓它工作。

public static Load CreateBuilder(IDataRecord dataRecord) 
    { 
     var dynamicBuilder = new DynamicBuilder<T>(); 

     var method = new DynamicMethod("DynamicCreate", typeof(T), new[] { typeof(IDataRecord) }, typeof(T), true); 
     var generator = method.GetILGenerator(); 

     var result = generator.DeclareLocal(typeof(T)); 
     generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); 
     generator.Emit(OpCodes.Stloc, result); 


     // Dictionary to store. 
     var dictType = typeof (Dictionary<string, object>); 
     var dict = typeof(T).GetProperty("CustomFields"); 
     var addMethod = dictType.GetMethod("Add"); 

     for (var i = 0; i < dataRecord.FieldCount; i++) 
     { 
      var propertyInfo = typeof(T).GetProperty(dataRecord.GetName(i)); 
      var endIfLabel = generator.DefineLabel(); 

      if (propertyInfo != null && propertyInfo.GetSetMethod() != null) 
      { 
       var attributes = propertyInfo.GetCustomAttributes(typeof(DbIgnore), true) as DbIgnore[]; 
       if (attributes != null && attributes.Length > 0) continue; 

       bool isNullable = false; 
       if (propertyInfo.PropertyType.Name.ToLower().Contains("nullable")) 
        isNullable = true; 

       Type _type = dataRecord.GetFieldType(i); 

       generator.Emit(OpCodes.Ldarg_0); 
       generator.Emit(OpCodes.Ldc_I4, i); 
       generator.Emit(OpCodes.Callvirt, IsDbNullMethod); 
       generator.Emit(OpCodes.Brtrue, endIfLabel); 

       generator.Emit(OpCodes.Ldloc, result); 
       generator.Emit(OpCodes.Ldarg_0); 
       generator.Emit(OpCodes.Ldc_I4, i); 
       generator.Emit(OpCodes.Callvirt, GetValueMethod); 

       if (isNullable) 
        generator.Emit(OpCodes.Unbox_Any, GetNullableType(_type)); 
       else 
        generator.Emit(OpCodes.Unbox_Any, _type); 

       //generator.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i)); 
       generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); 

       generator.MarkLabel(endIfLabel); 
      } else { 
        // How-To Add to Dictionary 
      } 
     } 

     generator.Emit(OpCodes.Ldloc, result); 
     generator.Emit(OpCodes.Ret); 

     return (Load)method.CreateDelegate(typeof(Load)); 
    } 
+0

什麼不行? – Gabe 2011-05-12 01:00:57

+0

我無法弄清楚如何引用對象上的Dictionary來調用addMethod。我可以創建一個新的dicitonary 'generator.DeclareLocal(dictType); generator.Emit(OpCodes.Newobj,dictType.GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc_1);'併爲其成功添加值,但不知道如何在類上引用字典 – rqmedes 2011-05-12 01:15:49

回答

1

在循環之外,從您的對象獲取Dictionary引用到本地變量中。

在循環內部,將保存字典變量,鍵和值的局部變量壓入堆棧,然後將callvirt發送到Add(TKey, TValue)方法。

+0

感謝我幾乎在那裏,如果我創建一個新的字典並在循環中添加值,即'generator.DeclareLocal(dictType); generator.Emit(OpCodes.Newobj,dictType.GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc_1);' 但似乎無法找到正確的語法來訪問類的一個。 – rqmedes 2011-05-12 01:05:06

+0

@rqmedes:不知道你的類是如何構造的,我不能確定,但​​我想你需要從'CustomFields'屬性讀取?嘗試'the_dict = generator.DeclareLocal(dictType); generator.Emit(OpCodes.Ldloc,result); generator.Emit(OpCodes.Callvirt,dict.GetGetMethod()); generator.Emit(OpCodes.Stloc,the_dict);' – 2011-05-12 02:01:30

+0

非常感謝,是它 – rqmedes 2011-05-12 02:30:44