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 }