2011-05-12 43 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