C#Emitダイナミックエージェントによるエンティティオブジェクトの生成

8759 ワード

 1   /// <summary>
 2     ///   Emit          
 3     /// </summary>
 4     /// <typeparam name="T">   </typeparam>
 5     public class TDynamicBuilder<T>
 6     {
 7         #region     
 8         private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod("get_Item", new[] { typeof(int) });
 9 
10         private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new[] { typeof(int) });
11 
12         private delegate T Load(IDataRecord dataRecord);
13 
14         /// <summary>
15         ///   
16         /// </summary>
17         private Load Handler;//                 IDataRecord  
18         #endregion
19 
20         #region     
21         private TDynamicBuilder() { }
22         #endregion
23 
24         #region +Build Emit            
25         /// <summary>
26         /// Emit            
27         /// </summary>
28         /// <param name="dataRecord">DataReader      </param>
29         /// <returns></returns>
30         public T Build(IDataRecord dataRecord)
31         {
32             return Handler(dataRecord);//  CreateBuilder    DynamicCreate       
33         }
34         #endregion
35 
36         #region + CreateBuilder     Builder 
37         /// <summary>
38         ///     Builder 
39         /// </summary>
40         /// <param name="dataRecord">DataReader      </param>
41         /// <returns></returns>
42         public static TDynamicBuilder<T> CreateBuilder(IDataRecord dataRecord)
43         {
44             var dynamicBuilder = new TDynamicBuilder<T>();
45             var type = typeof(T);
46             //      DynamicCreate     ,   typof(T),  typeof(IDataRecord)
47             var method = new DynamicMethod("DynamicCreate", type, new[] { typeof(IDataRecord) }, typeof(T), true);
48             var generator = method.GetILGenerator();//    MSIL   ,         
49             var result = generator.DeclareLocal(type);//              T t;    
50             //The next piece of code instantiates the requested type of object and stores it in the local variable.   t=new T();    
51             generator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
52             generator.Emit(OpCodes.Stloc, result);
53             var propertys = type.GetProperties();
54             //    
55             for (var i = 0; i < dataRecord.FieldCount; i++)
56             {
57                 //    
58                 var propertyInfo = propertys.FirstOrDefault(a => string.Equals(a.Name.ToLower(), dataRecord.GetName(i).ToLower()));
59                 if (propertyInfo == null) continue;
60                 if (!string.Equals(propertyInfo.Name, dataRecord.GetName(i), StringComparison.CurrentCultureIgnoreCase)) continue;
61                 //                        
62                 var endIfLabel = generator.DefineLabel();
63 
64                 /*The code then loops through the fields in the data reader, finding matching properties on the type passed in. 
65                  * When a match is found, the code checks to see if the value from the data reader is null.
66                  */
67                 generator.Emit(OpCodes.Ldarg_0);
68                 generator.Emit(OpCodes.Ldc_I4, i);
69                 //        IsDBNull     IsDBNull==true contine
70                 generator.Emit(OpCodes.Callvirt, isDBNullMethod);
71                 generator.Emit(OpCodes.Brtrue, endIfLabel);
72 
73                 /*If the value in the data reader is not null, the code sets the value on the object.*/
74                 generator.Emit(OpCodes.Ldloc, result);
75                 generator.Emit(OpCodes.Ldarg_0);
76                 generator.Emit(OpCodes.Ldc_I4, i);
77                 generator.Emit(OpCodes.Callvirt, getValueMethod); //  get_Item  
78                 generator.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i));
79                 generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); //         
80 
81                 generator.MarkLabel(endIfLabel);
82 
83             }
84 
85             /*The last part of the code returns the value of the local variable*/
86             generator.Emit(OpCodes.Ldloc, result);
87             generator.Emit(OpCodes.Ret);//88 
89             //         ,              ,       handler,handler Build   Invoke
90             dynamicBuilder.Handler = (Load)method.CreateDelegate(typeof(Load));
91             return dynamicBuilder;
92         }
93         #endregion
94 
95     }