0
|
1 using System;
|
|
2 using System.Collections;
|
|
3 using System.Collections.Generic;
|
|
4 using System.ComponentModel;
|
|
5 using System.Data;
|
|
6 using System.Linq;
|
|
7 using System.Reflection;
|
|
8 using System.Reflection.Emit;
|
|
9
|
|
10 using BLToolkit.Common;
|
|
11 using BLToolkit.Data;
|
|
12 using BLToolkit.Data.DataProvider;
|
|
13 using BLToolkit.Mapping;
|
|
14 using BLToolkit.Properties;
|
|
15 using BLToolkit.Reflection;
|
|
16 using BLToolkit.Reflection.Emit;
|
|
17 using BLToolkit.TypeBuilder;
|
|
18 using BLToolkit.TypeBuilder.Builders;
|
|
19
|
|
20 namespace BLToolkit.DataAccess
|
|
21 {
|
|
22 public class DataAccessorBuilder : AbstractTypeBuilderBase
|
|
23 {
|
|
24 struct MapOutputParametersValue
|
|
25 {
|
|
26 public readonly string ReturnValueMember;
|
|
27 public readonly ParameterInfo ParameterInfo;
|
|
28
|
|
29 public MapOutputParametersValue(string returnValueMember, ParameterInfo parameterInfo)
|
|
30 {
|
|
31 ReturnValueMember = returnValueMember;
|
|
32 ParameterInfo = parameterInfo;
|
|
33 }
|
|
34 }
|
|
35
|
|
36 public override int GetPriority(BuildContext context)
|
|
37 {
|
|
38 return TypeBuilderConsts.Priority.DataAccessor;
|
|
39 }
|
|
40
|
|
41 public override bool IsApplied(BuildContext context, AbstractTypeBuilderList builders)
|
|
42 {
|
|
43 if (context.IsBuildStep)
|
|
44 {
|
|
45 if (context.IsAbstractMethod)
|
|
46 {
|
|
47 // Give up if there is any builder that builds the method body.
|
|
48 //
|
|
49 if (builders.Count > 1)
|
|
50 foreach (IAbstractTypeBuilder builder in builders)
|
|
51 if (builder != this && builder.IsApplied(context, builders))
|
|
52 return false;
|
|
53
|
|
54 return true;
|
|
55 }
|
|
56
|
|
57 // Treat an abstract getter/setter as a regular method
|
|
58 // when the property has [NoInstance] attribute
|
|
59 //
|
|
60 if (context.IsAbstractGetter || context.IsAbstractSetter)
|
|
61 return context.CurrentProperty.IsDefined(typeof(NoInstanceAttribute), true);
|
|
62 }
|
|
63
|
|
64 return false;
|
|
65 }
|
|
66
|
|
67 private Dictionary<Type, Type> _actualTypes;
|
|
68 private Dictionary<Type, Type> ActualTypes
|
|
69 {
|
|
70 get
|
|
71 {
|
|
72 if (_actualTypes == null)
|
|
73 {
|
|
74 _actualTypes = new Dictionary<Type, Type>();
|
|
75
|
|
76 object[] attrs = Context.Type.GetAttributes(typeof(ActualTypeAttribute));
|
|
77
|
|
78 foreach (ActualTypeAttribute attr in attrs)
|
|
79 if (!_actualTypes.ContainsKey(attr.BaseType))
|
|
80 _actualTypes.Add(attr.BaseType, attr.ActualType);
|
|
81 }
|
|
82
|
|
83 return _actualTypes;
|
|
84 }
|
|
85 }
|
|
86
|
|
87 enum ReturnType
|
|
88 {
|
|
89 DataReader,
|
|
90 DataSet,
|
|
91 DataTable,
|
|
92 List,
|
|
93 Dictionary,
|
|
94 Enumerable,
|
|
95 Void,
|
|
96 Scalar,
|
|
97 Object
|
|
98 }
|
|
99
|
|
100 static ReturnType GetReturnType(Type returnType)
|
|
101 {
|
|
102 if (returnType == typeof(IDataReader))
|
|
103 return ReturnType.DataReader;
|
|
104
|
|
105 if (returnType == typeof(DataSet) || returnType.IsSubclassOf(typeof(DataSet)))
|
|
106 return ReturnType.DataSet;
|
|
107
|
|
108 if (returnType == typeof(DataTable) || returnType.IsSubclassOf(typeof(DataTable)))
|
|
109 return ReturnType.DataTable;
|
|
110
|
|
111 if (!returnType.IsArray &&
|
|
112 (IsInterfaceOf(returnType, typeof(IList)) ||
|
|
113 returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(IList<>)))
|
|
114 return ReturnType.List;
|
|
115
|
|
116 if (IsInterfaceOf(returnType, typeof(IDictionary)) ||
|
|
117 returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
|
|
118 return ReturnType.Dictionary;
|
|
119
|
|
120 if (returnType == typeof(IEnumerable) ||
|
|
121 returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
|
|
122 return ReturnType.Enumerable;
|
|
123
|
|
124 if (returnType == typeof(void))
|
|
125 return ReturnType.Void;
|
|
126
|
|
127 if (TypeHelper.IsScalar(returnType.IsByRef ? returnType.GetElementType() : returnType))
|
|
128 return ReturnType.Scalar;
|
|
129
|
|
130 return ReturnType.Object;
|
|
131 }
|
|
132
|
|
133 void ThrowTypeBuilderException(string message)
|
|
134 {
|
|
135 throw new TypeBuilderException(
|
|
136 string.Format(message, Context.CurrentMethod.DeclaringType.Name, Context.CurrentMethod.Name));
|
|
137 }
|
|
138
|
|
139 const BindingFlags _bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
|
140
|
|
141 readonly Type _baseType = typeof(DataAccessor);
|
|
142 Type _objectType;
|
|
143 bool _explicitObjectType;
|
|
144 ParameterInfo[] _parameters;
|
|
145 ArrayList _paramList;
|
|
146 ArrayList _refParamList;
|
|
147 bool _createManager;
|
|
148 LocalBuilder _locManager;
|
|
149 LocalBuilder _locObjType;
|
|
150 ArrayList _outputParameters;
|
|
151 SqlQueryAttribute _sqlQueryAttribute;
|
|
152 ArrayList _formatParamList;
|
|
153 ParameterInfo _destination;
|
|
154 ArrayList _mapOutputParameters;
|
|
155
|
|
156 protected override void BuildAbstractMethod()
|
|
157 {
|
|
158 // Any class variable must be initialized before use
|
|
159 // as the same instance of the class is utilized to build abstract methods.
|
|
160 //
|
|
161 _paramList = new ArrayList();
|
|
162 _refParamList = new ArrayList();
|
|
163 _formatParamList = new ArrayList();
|
|
164 _mapOutputParameters = new ArrayList();
|
|
165 _destination = null;
|
|
166 _createManager = true;
|
|
167 _objectType = null;
|
|
168 _explicitObjectType = false;
|
|
169 _parameters = Context.CurrentMethod.GetParameters();
|
|
170 _locManager = Context.MethodBuilder.Emitter.DeclareLocal(typeof(DbManager));
|
|
171 _locObjType = Context.MethodBuilder.Emitter.DeclareLocal(typeof(Type));
|
|
172 _outputParameters = null;
|
|
173 _sqlQueryAttribute = null;
|
|
174
|
|
175 GetSqlQueryAttribute();
|
|
176 ProcessParameters();
|
|
177
|
|
178 var returnType = MethodReturnType;
|
|
179 var rt = GetReturnType(returnType);
|
|
180
|
|
181 CreateDbManager(rt != ReturnType.Enumerable);
|
|
182 SetObjectType();
|
|
183
|
|
184 // Define execution method type.
|
|
185 //
|
|
186 switch (rt)
|
|
187 {
|
|
188 case ReturnType.DataReader : ExecuteReader(); break;
|
|
189 case ReturnType.DataSet : ExecuteDataSet(returnType); break;
|
|
190 case ReturnType.DataTable : ExecuteDataTable(); break;
|
|
191 case ReturnType.Void : ExecuteNonQuery(); break;
|
|
192 case ReturnType.Scalar : ExecuteScalar(); break;
|
|
193 case ReturnType.Enumerable : ExecuteEnumerable(); break;
|
|
194
|
|
195 case ReturnType.List:
|
|
196
|
|
197 if (!_explicitObjectType)
|
|
198 {
|
|
199 Type elementType = TypeHelper.GetListItemType(returnType);
|
|
200
|
|
201 if (elementType == typeof(object) && _destination != null)
|
|
202 elementType = TypeHelper.GetListItemType(Context.CurrentMethod.ReturnType);
|
|
203
|
|
204 if (elementType != typeof(object))
|
|
205 _objectType = elementType;
|
|
206
|
|
207 if (ActualTypes.ContainsKey(_objectType))
|
|
208 _objectType = ActualTypes[_objectType];
|
|
209 }
|
|
210
|
|
211 if (_objectType == null || _objectType == typeof(object))
|
|
212 ThrowTypeBuilderException(Resources.DataAccessorBuilder_BadListItemType);
|
|
213
|
|
214 if (TypeHelper.IsScalar(_objectType))
|
|
215 ExecuteScalarList();
|
|
216 else
|
|
217 ExecuteList();
|
|
218
|
|
219 break;
|
|
220
|
|
221 case ReturnType.Dictionary:
|
|
222 {
|
|
223 Type elementType = null;
|
|
224 Type keyType = typeof(object);
|
|
225 Type[] gTypes = TypeHelper.GetGenericArguments(returnType, typeof(IDictionary));
|
|
226
|
|
227 if ((gTypes == null || gTypes.Length != 2) && _destination != null)
|
|
228 gTypes = TypeHelper.GetGenericArguments(_destination.ParameterType, typeof(IDictionary));
|
|
229
|
|
230 if (gTypes != null && gTypes.Length == 2)
|
|
231 {
|
|
232 keyType = gTypes[0];
|
|
233 elementType = gTypes[1];
|
|
234 }
|
|
235
|
|
236 if (elementType == null || _explicitObjectType)
|
|
237 elementType = _objectType;
|
|
238
|
|
239 if (elementType == null || elementType == typeof(object))
|
|
240 ThrowTypeBuilderException(Resources.DataAccessorBuilder_BadListItemType);
|
|
241
|
|
242 bool isIndex = TypeHelper.IsSameOrParent(typeof(CompoundValue), keyType);
|
|
243
|
|
244 if (keyType != typeof(object) && !isIndex && !TypeHelper.IsScalar(keyType))
|
|
245 ThrowTypeBuilderException(
|
|
246 Resources.DataAccessorBuilder_BadKeyType);
|
|
247
|
|
248 MethodInfo mi = Context.CurrentMethod;
|
|
249
|
|
250 object[] attrs = mi.GetCustomAttributes(typeof(IndexAttribute), true);
|
|
251 NameOrIndexParameter[] fields = new NameOrIndexParameter[0];
|
|
252
|
|
253 if (attrs.Length != 0)
|
|
254 fields = ((IndexAttribute)attrs[0]).Fields;
|
|
255
|
|
256 if (fields.Length > 1 && keyType != typeof(object) && !isIndex)
|
|
257 ThrowTypeBuilderException(
|
|
258 Resources.DataAccessor_InvalidKeyType);
|
|
259
|
|
260 if (TypeHelper.IsScalar(elementType))
|
|
261 {
|
|
262 attrs = mi.GetCustomAttributes(typeof(ScalarFieldNameAttribute), true);
|
|
263
|
|
264 if (attrs.Length == 0)
|
|
265 ThrowTypeBuilderException(Resources.DataAccessorBuilder_ScalarFieldNameMissing);
|
|
266
|
|
267 NameOrIndexParameter scalarField = ((ScalarFieldNameAttribute)attrs[0]).NameOrIndex;
|
|
268
|
|
269 if (fields.Length == 0)
|
|
270 ExecuteScalarDictionaryWithPK(keyType, scalarField, elementType);
|
|
271 else if (isIndex || fields.Length > 1)
|
|
272 ExecuteScalarDictionaryWithMapIndex(fields, scalarField, elementType);
|
|
273 else
|
|
274 ExecuteScalarDictionaryWithScalarKey(fields[0], keyType, scalarField, elementType);
|
|
275 }
|
|
276 else
|
|
277 {
|
|
278 if (!_explicitObjectType && ActualTypes.ContainsKey(elementType))
|
|
279 elementType = ActualTypes[elementType];
|
|
280
|
|
281 if (fields.Length == 0)
|
|
282 ExecuteDictionaryWithPK(keyType, elementType);
|
|
283 else if (isIndex || fields.Length > 1)
|
|
284 ExecuteDictionaryWithMapIndex(fields, elementType);
|
|
285 else
|
|
286 ExecuteDictionaryWithScalarKey(fields[0], elementType);
|
|
287 }
|
|
288 }
|
|
289
|
|
290 break;
|
|
291
|
|
292 default:
|
|
293
|
|
294 if (_objectType == null || !TypeHelper.IsSameOrParent(returnType, _objectType))
|
|
295 _objectType = returnType;
|
|
296
|
|
297 if (!_explicitObjectType && ActualTypes.ContainsKey(_objectType))
|
|
298 _objectType = ActualTypes[_objectType];
|
|
299
|
|
300 ExecuteObject();
|
|
301
|
|
302 break;
|
|
303 }
|
|
304
|
|
305 GetOutRefParameters();
|
|
306
|
|
307 if (rt != ReturnType.Enumerable)
|
|
308 Finally();
|
|
309 }
|
|
310
|
|
311 protected override void BuildAbstractGetter()
|
|
312 {
|
|
313 BuildAbstractMethod();
|
|
314 }
|
|
315
|
|
316 protected override void BuildAbstractSetter()
|
|
317 {
|
|
318 BuildAbstractMethod();
|
|
319 }
|
|
320
|
|
321 void GetSqlQueryAttribute()
|
|
322 {
|
|
323 object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(SqlQueryAttribute), true);
|
|
324
|
|
325 if (attrs.Length != 0)
|
|
326 _sqlQueryAttribute = (SqlQueryAttribute)attrs[0];
|
|
327 }
|
|
328
|
|
329 void AddParameter(ParameterInfo pi)
|
|
330 {
|
|
331 Type pType = pi.ParameterType;
|
|
332
|
|
333 if (pType.IsByRef)
|
|
334 pType = pType.GetElementType();
|
|
335
|
|
336 if (TypeHelper.IsScalar(pType)
|
|
337 #if FW4
|
|
338 || pi.IsRefCursor()
|
|
339 #endif
|
|
340 )
|
|
341 _paramList.Add(pi);
|
|
342 else if (pType == typeof(DbManager) || pType.IsSubclassOf(typeof(DbManager)))
|
|
343 _createManager = false;
|
|
344 else
|
|
345 _refParamList.Add(pi);
|
|
346 }
|
|
347
|
|
348 void ProcessParameters()
|
|
349 {
|
|
350 for (int i = 0; i < _parameters.Length; i++)
|
|
351 {
|
|
352 ParameterInfo pi = _parameters[i];
|
|
353 NoMapAttribute[] attrs = (NoMapAttribute[])pi.GetCustomAttributes(typeof(NoMapAttribute), true);
|
|
354
|
|
355 if (attrs.Length == 0)
|
|
356 AddParameter(pi);
|
|
357 else
|
|
358 {
|
|
359 for (int j = 0; j < attrs.Length; ++j)
|
|
360 {
|
|
361 if (!attrs[j].NoMap)
|
|
362 AddParameter(pi);
|
|
363
|
|
364 if (attrs[j] is FormatAttribute)
|
|
365 {
|
|
366 int index = ((FormatAttribute)attrs[j]).Index;
|
|
367
|
|
368 if (index < 0)
|
|
369 index = 0;
|
|
370 else if (index > _formatParamList.Count)
|
|
371 index = _formatParamList.Count;
|
|
372
|
|
373 _formatParamList.Insert(index, pi);
|
|
374 }
|
|
375 else if (attrs[j] is DestinationAttribute)
|
|
376 {
|
|
377 if (_destination != null)
|
|
378 throw new TypeBuilderException(Resources.DataAccessorBuilderTooManyDestinations);
|
|
379
|
|
380 _destination = pi;
|
|
381 }
|
|
382 }
|
|
383 }
|
|
384 }
|
|
385 }
|
|
386
|
|
387 void CreateDbManager(bool beginException)
|
|
388 {
|
|
389 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
390
|
|
391 if (_createManager)
|
|
392 {
|
|
393 emit
|
|
394 .ldarg_0
|
|
395 .callvirt(_baseType, "GetDbManager")
|
|
396 .stloc(_locManager);
|
|
397
|
|
398 if (beginException)
|
|
399 emit.BeginExceptionBlock();
|
|
400 }
|
|
401 else
|
|
402 {
|
|
403 for (int i = 0; i < _parameters.Length; i++)
|
|
404 {
|
|
405 Type pType = _parameters[i].ParameterType;
|
|
406
|
|
407 if (pType == typeof(DbManager) || pType.IsSubclassOf(typeof(DbManager)))
|
|
408 {
|
|
409 emit
|
|
410 .ldarg(_parameters[i])
|
|
411 .stloc(_locManager)
|
|
412 ;
|
|
413
|
|
414 break;
|
|
415 }
|
|
416 }
|
|
417 }
|
|
418 }
|
|
419
|
|
420 void SetObjectType()
|
|
421 {
|
|
422 var mi = Context.CurrentMethod;
|
|
423 var attrs = mi.GetCustomAttributes(typeof(ObjectTypeAttribute), true);
|
|
424
|
|
425 if (attrs.Length == 0)
|
|
426 attrs = mi.DeclaringType.GetCustomAttributes(typeof(ObjectTypeAttribute), true);
|
|
427 else
|
|
428 _explicitObjectType = true;
|
|
429
|
|
430 if (attrs.Length != 0)
|
|
431 _objectType = ((ObjectTypeAttribute)attrs[0]).ObjectType;
|
|
432
|
|
433 if (_objectType == null)
|
|
434 {
|
|
435 var types = TypeHelper.GetGenericArguments(mi.DeclaringType, typeof(DataAccessor));
|
|
436
|
|
437 if (types != null)
|
|
438 _objectType = types[0];
|
|
439 }
|
|
440 }
|
|
441
|
|
442 #region ExecuteReader
|
|
443
|
|
444 void ExecuteReader()
|
|
445 {
|
|
446 InitObjectType();
|
|
447 GetSprocNameOrSqlQueryTest();
|
|
448 CallSetCommand();
|
|
449
|
|
450 var attrs = Context.CurrentMethod.GetCustomAttributes(typeof(CommandBehaviorAttribute), true);
|
|
451
|
|
452 if (attrs.Length == 0)
|
|
453 {
|
|
454 Context.MethodBuilder.Emitter
|
|
455 .callvirt(typeof(DbManager).GetMethod("ExecuteReader", Type.EmptyTypes))
|
|
456 .stloc(Context.ReturnValue)
|
|
457 ;
|
|
458 }
|
|
459 else
|
|
460 {
|
|
461 Context.MethodBuilder.Emitter
|
|
462 .ldc_i4_((int)((CommandBehaviorAttribute)attrs[0]).CommandBehavior)
|
|
463 .callvirt(typeof(DbManager), "ExecuteReader", typeof(CommandBehavior))
|
|
464 .stloc(Context.ReturnValue)
|
|
465 ;
|
|
466 }
|
|
467 }
|
|
468
|
|
469 #endregion
|
|
470
|
|
471 #region ExecuteDataSet
|
|
472
|
|
473 void ExecuteDataSet(Type returnType)
|
|
474 {
|
|
475 CreateReturnTypeInstance();
|
|
476 InitObjectType();
|
|
477 GetSprocNameOrSqlQueryTest();
|
|
478 CallSetCommand();
|
|
479
|
|
480 var emit = Context.MethodBuilder.Emitter;
|
|
481
|
|
482 if (returnType == typeof(DataSet))
|
|
483 {
|
|
484 LoadDestinationOrReturnValue();
|
|
485
|
|
486 object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(DataSetTableAttribute), true);
|
|
487
|
|
488 if (attrs.Length == 0)
|
|
489 {
|
|
490 emit
|
|
491 .callvirt(typeof(DbManager), "ExecuteDataSet", typeof(DataSet))
|
|
492 .pop
|
|
493 .end()
|
|
494 ;
|
|
495 }
|
|
496 else
|
|
497 {
|
|
498 emit
|
|
499 .ldNameOrIndex(((DataSetTableAttribute)attrs[0]).NameOrIndex)
|
|
500 .callvirt(typeof(DbManager), "ExecuteDataSet", typeof(DataSet), typeof(NameOrIndexParameter))
|
|
501 .pop
|
|
502 .end()
|
|
503 ;
|
|
504 }
|
|
505 }
|
|
506 else
|
|
507 {
|
|
508 emit
|
|
509 .pop
|
|
510 .end()
|
|
511 ;
|
|
512
|
|
513 LoadDestinationOrReturnValue();
|
|
514
|
|
515 Label l1 = emit.DefineLabel();
|
|
516 Label l2 = emit.DefineLabel();
|
|
517
|
|
518 emit
|
|
519 .callvirt(typeof(DataSet).GetProperty("Tables").GetGetMethod())
|
|
520 .callvirt(typeof(InternalDataCollectionBase).GetProperty("Count").GetGetMethod())
|
|
521 .ldc_i4_0
|
|
522 .ble_s(l1)
|
|
523 .ldloc(_locManager);
|
|
524
|
|
525 LoadDestinationOrReturnValue();
|
|
526
|
|
527 object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(DataSetTableAttribute), true);
|
|
528
|
|
529 if (attrs.Length == 0)
|
|
530 {
|
|
531 LoadDestinationOrReturnValue();
|
|
532
|
|
533 emit
|
|
534 .callvirt(typeof(DataSet).GetProperty("Tables").GetGetMethod())
|
|
535 .ldc_i4_0
|
|
536 .callvirt(typeof(DataTableCollection), "get_Item", typeof(int))
|
|
537 .callvirt(typeof(DataTable).GetProperty("TableName").GetGetMethod())
|
|
538 .call(typeof(NameOrIndexParameter), "op_Implicit", typeof(string))
|
|
539 ;
|
|
540 }
|
|
541 else
|
|
542 {
|
|
543 emit
|
|
544 .ldNameOrIndex(((DataSetTableAttribute)attrs[0]).NameOrIndex)
|
|
545 ;
|
|
546 }
|
|
547
|
|
548 emit
|
|
549 .callvirt(typeof(DbManager), "ExecuteDataSet", typeof(DataSet), typeof(NameOrIndexParameter))
|
|
550 .pop
|
|
551 .br_s(l2)
|
|
552 .MarkLabel(l1)
|
|
553 .ldloc(_locManager);
|
|
554
|
|
555 LoadDestinationOrReturnValue();
|
|
556
|
|
557 emit
|
|
558 .callvirt(typeof(DbManager), "ExecuteDataSet", typeof(DataSet))
|
|
559 .pop
|
|
560 .MarkLabel(l2)
|
|
561 ;
|
|
562 }
|
|
563 }
|
|
564
|
|
565 #endregion
|
|
566
|
|
567 #region ExecuteDataTable
|
|
568
|
|
569 void ExecuteDataTable()
|
|
570 {
|
|
571 CreateReturnTypeInstance();
|
|
572 InitObjectType();
|
|
573 GetSprocNameOrSqlQueryTest();
|
|
574 CallSetCommand();
|
|
575 LoadDestinationOrReturnValue();
|
|
576
|
|
577 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
578
|
|
579 emit
|
|
580 .callvirt(typeof(DbManager), "ExecuteDataTable", typeof(DataTable))
|
|
581 .pop
|
|
582 .end()
|
|
583 ;
|
|
584
|
|
585 // When DataSetTableAttribute is present, simply set table name to the name specified.
|
|
586 //
|
|
587 object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(DataSetTableAttribute), true);
|
|
588
|
|
589 if (attrs.Length != 0)
|
|
590 {
|
|
591 DataSetTableAttribute attr = (DataSetTableAttribute)attrs[0];
|
|
592
|
|
593 if (!attr.NameOrIndex.ByName)
|
|
594 throw new TypeBuilderException(string.Format(
|
|
595 Resources.DataAccessorBuilder_DataSetTableMustBeByName,
|
|
596 Context.CurrentMethod.DeclaringType.Name, Context.CurrentMethod.Name));
|
|
597
|
|
598 LoadDestinationOrReturnValue();
|
|
599
|
|
600 emit
|
|
601 .ldstr(attr.NameOrIndex.Name)
|
|
602 .callvirt(typeof(DataTable), "set_TableName", typeof(string))
|
|
603 ;
|
|
604 }
|
|
605 }
|
|
606
|
|
607 #endregion
|
|
608
|
|
609 #region ExecuteScalarList
|
|
610
|
|
611 void ExecuteScalarList()
|
|
612 {
|
|
613 CreateReturnTypeInstance();
|
|
614 InitObjectType();
|
|
615 GetSprocNameOrSqlQueryTest();
|
|
616 CallSetCommand();
|
|
617 LoadDestinationOrReturnValue();
|
|
618
|
|
619 object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(ScalarFieldNameAttribute), true);
|
|
620
|
|
621 if (attrs.Length == 0)
|
|
622 {
|
|
623 Context.MethodBuilder.Emitter
|
|
624 .ldloc(_locObjType)
|
|
625 .callvirt(typeof(DbManager), "ExecuteScalarList", typeof(IList), typeof(Type))
|
|
626 .pop
|
|
627 .end()
|
|
628 ;
|
|
629 }
|
|
630 else
|
|
631 {
|
|
632 Context.MethodBuilder.Emitter
|
|
633 .ldloc(_locObjType)
|
|
634 .ldNameOrIndex(((ScalarFieldNameAttribute)attrs[0]).NameOrIndex)
|
|
635 .callvirt(typeof(DbManager), "ExecuteScalarList", typeof(IList), typeof(Type), typeof(NameOrIndexParameter))
|
|
636 .pop
|
|
637 .end()
|
|
638 ;
|
|
639 }
|
|
640 }
|
|
641
|
|
642 void ExecuteList()
|
|
643 {
|
|
644 CreateReturnTypeInstance();
|
|
645 InitObjectType();
|
|
646 GetSprocNameOrSqlQueryTest();
|
|
647 CallSetCommand();
|
|
648 LoadDestinationOrReturnValue();
|
|
649
|
|
650 Context.MethodBuilder.Emitter
|
|
651 .CastIfNecessary(typeof(IList), MethodReturnType)
|
|
652 .ldloc(_locObjType)
|
|
653 .callvirt(typeof(DbManager), "ExecuteList", typeof(IList), typeof(Type))
|
|
654 .pop
|
|
655 .end()
|
|
656 ;
|
|
657 }
|
|
658
|
|
659 #endregion
|
|
660
|
|
661 #region ExecuteDictionary
|
|
662
|
|
663 public FieldBuilder GetIndexField(NameOrIndexParameter[] namesOrIndexes)
|
|
664 {
|
|
665 var id = "index$" + string.Join("%",
|
|
666 Array.ConvertAll<NameOrIndexParameter, string>(namesOrIndexes,
|
|
667 delegate(NameOrIndexParameter nameOrIndex)
|
|
668 {
|
|
669 return nameOrIndex.ToString();
|
|
670 }));
|
|
671
|
|
672 var fieldBuilder = Context.GetField(id);
|
|
673
|
|
674 if (fieldBuilder == null)
|
|
675 {
|
|
676 fieldBuilder = Context.CreatePrivateStaticField(id, typeof(MapIndex));
|
|
677
|
|
678 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
|
|
679
|
|
680 emit
|
|
681 .ldc_i4_(namesOrIndexes.Length)
|
|
682 .newarr(typeof(NameOrIndexParameter))
|
|
683 ;
|
|
684
|
|
685 for (int i = 0; i < namesOrIndexes.Length; i++)
|
|
686 {
|
|
687 emit
|
|
688 .dup
|
|
689 .ldc_i4_(i)
|
|
690 .ldelema(typeof(NameOrIndexParameter));
|
|
691
|
|
692 if (namesOrIndexes[i].ByName)
|
|
693 {
|
|
694 emit
|
|
695 .ldstr(namesOrIndexes[i].Name)
|
|
696 .call(typeof(NameOrIndexParameter), "op_Implicit", typeof(string));
|
|
697 }
|
|
698 else
|
|
699 {
|
|
700 emit
|
|
701 .ldc_i4_(namesOrIndexes[i].Index)
|
|
702 .call(typeof(NameOrIndexParameter), "op_Implicit", typeof(int));
|
|
703 }
|
|
704
|
|
705 emit
|
|
706 .stobj(typeof(NameOrIndexParameter))
|
|
707 .end()
|
|
708 ;
|
|
709 }
|
|
710
|
|
711 emit
|
|
712 .newobj(typeof(MapIndex), typeof(NameOrIndexParameter[]))
|
|
713 .stsfld(fieldBuilder)
|
|
714 ;
|
|
715 }
|
|
716
|
|
717 return fieldBuilder;
|
|
718 }
|
|
719
|
|
720 /// <summary>
|
|
721 /// Maps primary keys(s) to a scalar field.
|
|
722 /// </summary>
|
|
723 void ExecuteScalarDictionaryWithPK(
|
|
724 Type keyType,
|
|
725 NameOrIndexParameter scalarField,
|
|
726 Type elementType)
|
|
727 {
|
|
728 CreateReturnTypeInstance();
|
|
729 InitObjectType();
|
|
730
|
|
731 Context.MethodBuilder.Emitter
|
|
732 .ldarg_0
|
|
733 .end()
|
|
734 ;
|
|
735
|
|
736 GetSprocNameOrSqlQueryTest();
|
|
737 CallSetCommand();
|
|
738 LoadDestinationOrReturnValue();
|
|
739
|
|
740 Context.MethodBuilder.Emitter
|
|
741 .ldloc(_locObjType)
|
|
742 .LoadType(keyType)
|
|
743 .ldstr(Context.CurrentMethod.Name)
|
|
744 .ldNameOrIndex(scalarField)
|
|
745 .LoadType(elementType)
|
|
746 .callvirt(_baseType, "ExecuteScalarDictionary", _bindingFlags,
|
|
747 typeof(DbManager), typeof(IDictionary), typeof(Type),
|
|
748 typeof(Type), typeof(string), typeof(NameOrIndexParameter), typeof(Type))
|
|
749 ;
|
|
750 }
|
|
751
|
|
752 /// <summary>
|
|
753 /// Maps a complex index to a scalar field.
|
|
754 /// </summary>
|
|
755 void ExecuteScalarDictionaryWithMapIndex(
|
|
756 NameOrIndexParameter[] index,
|
|
757 NameOrIndexParameter scalarField,
|
|
758 Type elementType)
|
|
759 {
|
|
760 _objectType = elementType;
|
|
761
|
|
762 CreateReturnTypeInstance();
|
|
763 InitObjectType();
|
|
764 GetSprocNameOrSqlQueryTest();
|
|
765 CallSetCommand();
|
|
766 LoadDestinationOrReturnValue();
|
|
767
|
|
768 Context.MethodBuilder.Emitter
|
|
769 .ldsfld(GetIndexField(index))
|
|
770 .ldNameOrIndex(scalarField)
|
|
771 .ldloc(_locObjType)
|
|
772 .callvirt(typeof(DbManager), "ExecuteScalarDictionary",
|
|
773 typeof(IDictionary), typeof(MapIndex),
|
|
774 typeof(NameOrIndexParameter), typeof(Type))
|
|
775 .pop
|
|
776 .end()
|
|
777 ;
|
|
778 }
|
|
779
|
|
780 /// <summary>
|
|
781 /// Maps any single field to any (other) single field.
|
|
782 /// </summary>
|
|
783 void ExecuteScalarDictionaryWithScalarKey(
|
|
784 NameOrIndexParameter keyField, Type keyType,
|
|
785 NameOrIndexParameter scalarField, Type elementType)
|
|
786 {
|
|
787 _objectType = elementType;
|
|
788
|
|
789 CreateReturnTypeInstance();
|
|
790 InitObjectType();
|
|
791 GetSprocNameOrSqlQueryTest();
|
|
792 CallSetCommand();
|
|
793 LoadDestinationOrReturnValue();
|
|
794
|
|
795 Context.MethodBuilder.Emitter
|
|
796 .ldNameOrIndex(keyField)
|
|
797 .LoadType(keyType)
|
|
798 .ldNameOrIndex(scalarField)
|
|
799 .ldloc(_locObjType)
|
|
800 .callvirt(typeof(DbManager), "ExecuteScalarDictionary",
|
|
801 typeof(IDictionary), typeof(NameOrIndexParameter), typeof(Type),
|
|
802 typeof(NameOrIndexParameter), typeof(Type))
|
|
803 .pop
|
|
804 .end()
|
|
805 ;
|
|
806 }
|
|
807
|
|
808 /// <summary>
|
|
809 /// Maps primary keys(s) to an object of the specified type.
|
|
810 /// </summary>
|
|
811 void ExecuteDictionaryWithPK(
|
|
812 Type keyType,
|
|
813 Type elementType)
|
|
814 {
|
|
815 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
816
|
|
817 _objectType = elementType;
|
|
818
|
|
819 CreateReturnTypeInstance();
|
|
820 InitObjectType();
|
|
821
|
|
822 emit
|
|
823 .ldarg_0
|
|
824 .end()
|
|
825 ;
|
|
826
|
|
827 GetSprocNameOrSqlQueryTest();
|
|
828 CallSetCommand();
|
|
829 LoadDestinationOrReturnValue();
|
|
830
|
|
831 if (IsGenericDestinationOrReturnValue())
|
|
832 {
|
|
833 Type[] genericArgs = Context.ReturnValue.LocalType.GetGenericArguments();
|
|
834 Type[] types = new Type[]
|
|
835 {
|
|
836 typeof(DbManager),
|
|
837 typeof(IDictionary<,>).MakeGenericType(genericArgs),
|
|
838 typeof(Type),
|
|
839 typeof(string),
|
|
840 };
|
|
841 MethodInfo method = _baseType.GetMethod("ExecuteDictionary",
|
|
842 _bindingFlags, GenericBinder.Generic, types, null);
|
|
843
|
|
844 if (TypeHelper.IsSameOrParent(typeof(CompoundValue), genericArgs[0]))
|
|
845 method = method.MakeGenericMethod(genericArgs[1]);
|
|
846 else
|
|
847 method = method.MakeGenericMethod(genericArgs);
|
|
848
|
|
849 emit
|
|
850 .ldloc(_locObjType)
|
|
851 .ldstr(Context.CurrentMethod.Name)
|
|
852 .callvirt(method)
|
|
853 ;
|
|
854 }
|
|
855 else
|
|
856
|
|
857 emit
|
|
858 .ldloc(_locObjType)
|
|
859 .LoadType(keyType)
|
|
860 .ldstr(Context.CurrentMethod.Name)
|
|
861 .callvirt(_baseType, "ExecuteDictionary", _bindingFlags,
|
|
862 typeof(DbManager), typeof(IDictionary), typeof(Type),
|
|
863 typeof(Type), typeof(string))
|
|
864 ;
|
|
865 }
|
|
866
|
|
867 /// <summary>
|
|
868 /// Maps a complex index to an object of the specified type.
|
|
869 /// </summary>
|
|
870 void ExecuteDictionaryWithMapIndex(
|
|
871 NameOrIndexParameter[] index,
|
|
872 Type elementType)
|
|
873 {
|
|
874 _objectType = elementType;
|
|
875
|
|
876 CreateReturnTypeInstance();
|
|
877 InitObjectType();
|
|
878 GetSprocNameOrSqlQueryTest();
|
|
879 CallSetCommand();
|
|
880 LoadDestinationOrReturnValue();
|
|
881
|
|
882 Context.MethodBuilder.Emitter
|
|
883 .ldsfld(GetIndexField(index))
|
|
884 .ldloc(_locObjType)
|
|
885 .ldnull
|
|
886 .callvirt(typeof(DbManager), "ExecuteDictionary",
|
|
887 typeof(IDictionary), typeof(MapIndex), typeof(Type), typeof(object[]))
|
|
888 .pop
|
|
889 .end()
|
|
890 ;
|
|
891 }
|
|
892
|
|
893 /// <summary>
|
|
894 /// Maps any single field to object type.
|
|
895 /// </summary>
|
|
896 void ExecuteDictionaryWithScalarKey(
|
|
897 NameOrIndexParameter keyField,
|
|
898 Type elementType)
|
|
899 {
|
|
900 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
901
|
|
902 _objectType = elementType;
|
|
903
|
|
904 CreateReturnTypeInstance();
|
|
905 InitObjectType();
|
|
906 GetSprocNameOrSqlQueryTest();
|
|
907 CallSetCommand();
|
|
908 LoadDestinationOrReturnValue();
|
|
909
|
|
910 if (IsGenericDestinationOrReturnValue())
|
|
911 {
|
|
912 Type[] genericArgs = Context.ReturnValue.LocalType.GetGenericArguments();
|
|
913 Type[] types = new Type[]
|
|
914 {
|
|
915 typeof(IDictionary<,>).MakeGenericType(genericArgs),
|
|
916 typeof(NameOrIndexParameter),
|
|
917 typeof(Type),
|
|
918 typeof(object[]),
|
|
919 };
|
|
920 MethodInfo method = typeof(DbManager).GetMethod("ExecuteDictionary", _bindingFlags, GenericBinder.Generic, types, null)
|
|
921 .MakeGenericMethod(genericArgs);
|
|
922
|
|
923 emit
|
|
924 .ldNameOrIndex(keyField)
|
|
925 .ldloc(_locObjType)
|
|
926 .ldnull
|
|
927 .callvirt(method)
|
|
928 .pop
|
|
929 .end()
|
|
930 ;
|
|
931 }
|
|
932 else
|
|
933 {
|
|
934 emit
|
|
935 .ldNameOrIndex(keyField)
|
|
936 .ldloc(_locObjType)
|
|
937 .ldnull
|
|
938 .callvirt(typeof(DbManager), "ExecuteDictionary", typeof(IDictionary), typeof(NameOrIndexParameter), typeof(Type), typeof(object[]))
|
|
939 .pop
|
|
940 .end()
|
|
941 ;
|
|
942 }
|
|
943 }
|
|
944
|
|
945 #endregion
|
|
946
|
|
947 #region ExecuteEnumerable
|
|
948
|
|
949 public void ExecuteEnumerable()
|
|
950 {
|
|
951 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
952 Type returnType = Context.CurrentMethod.ReturnType;
|
|
953
|
|
954 if (_objectType == null && returnType.IsGenericType)
|
|
955 _objectType = returnType.GetGenericArguments()[0];
|
|
956
|
|
957 if (_objectType == null || _objectType == typeof(object))
|
|
958 ThrowTypeBuilderException(Resources.DataAccessorBuilder_BadListItemType);
|
|
959
|
|
960 Type returnObjectType = returnType.IsGenericType ? returnType.GetGenericArguments()[0] : _objectType;
|
|
961
|
|
962 InitObjectType();
|
|
963
|
|
964 Context.MethodBuilder.Emitter
|
|
965 .ldarg_0
|
|
966 .end()
|
|
967 ;
|
|
968
|
|
969 GetSprocNameOrSqlQueryTest();
|
|
970 CallSetCommand();
|
|
971
|
|
972 Type[] genericArgs = new Type[] { returnObjectType };
|
|
973 Type[] types = new Type[] { typeof(DbManager), typeof(Type), typeof(bool), };
|
|
974 MethodInfo method = _baseType
|
|
975 .GetMethod("ExecuteEnumerable", _bindingFlags, GenericBinder.Generic, types, null)
|
|
976 .MakeGenericMethod(genericArgs);
|
|
977
|
|
978 emit
|
|
979 .LoadType(_objectType)
|
|
980 .ldc_i4_1
|
|
981 .callvirt(method)
|
|
982 .stloc(Context.ReturnValue)
|
|
983 ;
|
|
984 }
|
|
985
|
|
986 #endregion
|
|
987
|
|
988 #region ExecuteNonQuery
|
|
989
|
|
990 public void ExecuteNonQuery()
|
|
991 {
|
|
992 if (_destination != null)
|
|
993 throw new TypeBuilderException(Resources.DataAccessorBuilder_CantExecuteNonQueryToDestination);
|
|
994
|
|
995 InitObjectType();
|
|
996 GetSprocNameOrSqlQueryTest();
|
|
997 CallSetCommand();
|
|
998
|
|
999 MethodInfo mi = typeof(DbManager).GetMethod("ExecuteNonQuery", Type.EmptyTypes);
|
|
1000 LocalBuilder locExec = Context.MethodBuilder.Emitter.DeclareLocal(mi.ReturnType);
|
|
1001
|
|
1002 Context.MethodBuilder.Emitter
|
|
1003 .callvirt(mi)
|
|
1004 .stloc(locExec)
|
|
1005 ;
|
|
1006
|
|
1007 if (Context.ReturnValue != null)
|
|
1008 {
|
|
1009 Context.MethodBuilder.Emitter
|
|
1010 .ldloc(locExec)
|
|
1011 .stloc(Context.ReturnValue)
|
|
1012 ;
|
|
1013 }
|
|
1014 }
|
|
1015
|
|
1016 #endregion
|
|
1017
|
|
1018 #region ExecuteScalar
|
|
1019
|
|
1020 public void ExecuteScalar()
|
|
1021 {
|
|
1022 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1023 Type returnType = Context.CurrentMethod.ReturnType;
|
|
1024 Type scalarType;
|
|
1025
|
|
1026 if (_destination != null)
|
|
1027 {
|
|
1028 if (_destination.ParameterType.IsByRef)
|
|
1029 scalarType = _destination.ParameterType.GetElementType();
|
|
1030 else
|
|
1031 throw new TypeBuilderException(Resources.DataAccessorBuilder_ScalarDestinationIsNotByRef);
|
|
1032
|
|
1033 if (returnType != typeof(void) && !TypeHelper.IsSameOrParent(returnType, scalarType))
|
|
1034 {
|
|
1035 // object Foo(out int num) is valid,
|
|
1036 // IConvertible Foo(ref int num) is also ok,
|
|
1037 // but string Bar(out DateTime dt) is not
|
|
1038 //
|
|
1039 throw new TypeBuilderException(string.Format(
|
|
1040 Resources.DataAccessorBuilder_IncompatibleDestinationType,
|
|
1041 returnType.FullName, Context.CurrentMethod.Name, scalarType.FullName));
|
|
1042 }
|
|
1043 }
|
|
1044 else
|
|
1045 scalarType = returnType;
|
|
1046
|
|
1047 if (_destination != null)
|
|
1048 emit
|
|
1049 .ldarg(_destination)
|
|
1050 ;
|
|
1051
|
|
1052 emit
|
|
1053 .ldarg_0
|
|
1054 .ldloc(_locManager)
|
|
1055 ;
|
|
1056
|
|
1057 InitObjectType();
|
|
1058 GetSprocNameOrSqlQueryTest();
|
|
1059 CallSetCommand();
|
|
1060
|
|
1061 object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(ScalarSourceAttribute), true);
|
|
1062
|
|
1063 if (attrs.Length == 0)
|
|
1064 {
|
|
1065 emit
|
|
1066 .callvirtNoGenerics(typeof(DbManager), "ExecuteScalar")
|
|
1067 ;
|
|
1068 }
|
|
1069 else
|
|
1070 {
|
|
1071 ScalarSourceAttribute attr = (ScalarSourceAttribute)attrs[0];
|
|
1072
|
|
1073 emit
|
|
1074 .ldc_i4_((int)attr.ScalarType)
|
|
1075 .ldNameOrIndex(attr.NameOrIndex)
|
|
1076 .callvirtNoGenerics(typeof(DbManager), "ExecuteScalar", typeof(ScalarSourceType), typeof(NameOrIndexParameter));
|
|
1077 }
|
|
1078
|
|
1079 MethodInfo converter = GetConverterMethod(scalarType);
|
|
1080
|
|
1081 if (converter == null)
|
|
1082 {
|
|
1083 emit
|
|
1084 .LoadType(scalarType)
|
|
1085 .ldnull
|
|
1086 .callvirt(_baseType, "ConvertChangeType", _bindingFlags, typeof(DbManager), typeof(object), typeof(Type), typeof(object))
|
|
1087 .unboxIfValueType(scalarType)
|
|
1088 ;
|
|
1089
|
|
1090 }
|
|
1091 else
|
|
1092 {
|
|
1093 emit
|
|
1094 .ldnull
|
|
1095 .callvirt(converter)
|
|
1096 ;
|
|
1097 }
|
|
1098
|
|
1099 if (_destination != null)
|
|
1100 {
|
|
1101 emit
|
|
1102 .stind(scalarType)
|
|
1103 ;
|
|
1104
|
|
1105 // The return value and a destination both are present
|
|
1106 //
|
|
1107 if (Context.ReturnValue != null)
|
|
1108 {
|
|
1109 emit
|
|
1110 .ldargEx(_destination, false)
|
|
1111 ;
|
|
1112
|
|
1113 if (scalarType != returnType)
|
|
1114 emit
|
|
1115 .boxIfValueType(scalarType)
|
|
1116 .CastFromObject(returnType)
|
|
1117 ;
|
|
1118
|
|
1119 emit.stloc(Context.ReturnValue)
|
|
1120 ;
|
|
1121 }
|
|
1122 }
|
|
1123 else
|
|
1124 emit
|
|
1125 .stloc(Context.ReturnValue)
|
|
1126 ;
|
|
1127 }
|
|
1128
|
|
1129 #endregion
|
|
1130
|
|
1131 #region ExecuteObject
|
|
1132
|
|
1133 public void ExecuteObject()
|
|
1134 {
|
|
1135 InitObjectType();
|
|
1136 GetSprocNameOrSqlQueryTest();
|
|
1137 CallSetCommand();
|
|
1138
|
|
1139 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1140
|
|
1141 if (_destination != null)
|
|
1142 {
|
|
1143 emit
|
|
1144 .ldarg(_destination)
|
|
1145 .callvirt(typeof(DbManager), "ExecuteObject", typeof(Object))
|
|
1146 ;
|
|
1147 }
|
|
1148 else
|
|
1149 {
|
|
1150 emit
|
|
1151 .ldloc(_locObjType)
|
|
1152 .callvirt(typeof(DbManager), "ExecuteObject", typeof(Type))
|
|
1153 ;
|
|
1154 }
|
|
1155
|
|
1156 if (null != Context.ReturnValue)
|
|
1157 {
|
|
1158 emit
|
|
1159 .castclass(_objectType)
|
|
1160 .stloc(Context.ReturnValue)
|
|
1161 ;
|
|
1162 }
|
|
1163 else
|
|
1164 {
|
|
1165 emit
|
|
1166 .pop
|
|
1167 .end()
|
|
1168 ;
|
|
1169 }
|
|
1170 }
|
|
1171
|
|
1172 #endregion
|
|
1173
|
|
1174 void Finally()
|
|
1175 {
|
|
1176 if (_createManager)
|
|
1177 {
|
|
1178 Context.MethodBuilder.Emitter
|
|
1179 .BeginFinallyBlock()
|
|
1180 .ldarg_0
|
|
1181 .ldloc(_locManager)
|
|
1182 .callvirt(_baseType, "Dispose", _bindingFlags, typeof(DbManager))
|
|
1183 .EndExceptionBlock()
|
|
1184 ;
|
|
1185 }
|
|
1186 }
|
|
1187
|
|
1188 void CreateReturnTypeInstance()
|
|
1189 {
|
|
1190 if (null == Context.ReturnValue)
|
|
1191 return;
|
|
1192
|
|
1193 if (null != _destination)
|
|
1194 {
|
|
1195 Context.MethodBuilder.Emitter
|
|
1196 .ldarg(_destination)
|
|
1197 .CastIfNecessary(Context.ReturnValue.LocalType, _destination.ParameterType)
|
|
1198 .stloc(Context.ReturnValue)
|
|
1199 ;
|
|
1200 }
|
|
1201 else
|
|
1202 {
|
|
1203 Type returnType = Context.CurrentMethod.ReturnType;
|
|
1204
|
|
1205 if (returnType.IsInterface)
|
|
1206 {
|
|
1207 if (IsInterfaceOf(returnType, typeof(IList)))
|
|
1208 returnType = typeof(ArrayList);
|
|
1209 else if (IsInterfaceOf(returnType, typeof(IDictionary)))
|
|
1210 returnType = typeof(Hashtable);
|
|
1211 else if (returnType.GetGenericTypeDefinition() == typeof(IList<>))
|
|
1212 returnType = typeof(List<>).MakeGenericType(returnType.GetGenericArguments());
|
|
1213 else if (returnType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
|
|
1214 returnType = typeof(Dictionary<,>).MakeGenericType(returnType.GetGenericArguments());
|
|
1215 }
|
|
1216
|
|
1217 ConstructorInfo ci = TypeHelper.GetDefaultConstructor(returnType);
|
|
1218
|
|
1219 if (ci == null)
|
|
1220 throw new TypeBuilderException(string.Format(Resources.DataAccessorBuilder_CantCreateTypeInstance,
|
|
1221 Context.CurrentMethod.ReturnType.FullName));
|
|
1222
|
|
1223 Context.MethodBuilder.Emitter
|
|
1224 .newobj(ci)
|
|
1225 .stloc(Context.ReturnValue)
|
|
1226 ;
|
|
1227 }
|
|
1228 }
|
|
1229
|
|
1230 Type MethodReturnType
|
|
1231 {
|
|
1232 get
|
|
1233 {
|
|
1234 return _destination != null ?
|
|
1235 _destination.ParameterType :
|
|
1236 Context.CurrentMethod.ReturnType;
|
|
1237 }
|
|
1238 }
|
|
1239
|
|
1240 void LoadDestinationOrReturnValue()
|
|
1241 {
|
|
1242 if (_destination != null)
|
|
1243 Context.MethodBuilder.Emitter.ldarg(_destination);
|
|
1244 else
|
|
1245 Context.MethodBuilder.Emitter.ldloc(Context.ReturnValue);
|
|
1246 }
|
|
1247
|
|
1248 bool IsGenericDestinationOrReturnValue()
|
|
1249 {
|
|
1250 return _destination == null ?
|
|
1251 Context.ReturnValue.LocalType.IsGenericType :
|
|
1252 _destination.ParameterType.IsGenericType;
|
|
1253 }
|
|
1254
|
|
1255 void InitObjectType()
|
|
1256 {
|
|
1257 Context.MethodBuilder.Emitter
|
|
1258 .LoadType(_objectType)
|
|
1259 .stloc(_locObjType)
|
|
1260 ;
|
|
1261 }
|
|
1262
|
|
1263 static int _nameCounter;
|
|
1264 static int _uniqueQueryID;
|
|
1265
|
|
1266 void GetSprocNameOrSqlQueryTest()
|
|
1267 {
|
|
1268 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1269
|
|
1270 if (_sqlQueryAttribute != null)
|
|
1271 {
|
|
1272 emit
|
|
1273 .ldloc(_locManager)
|
|
1274 ;
|
|
1275
|
|
1276 if (_sqlQueryAttribute.ID != int.MinValue)
|
|
1277 {
|
|
1278 emit
|
|
1279 .ldarg_0
|
|
1280 .ldloc(_locManager)
|
|
1281 .ldc_i4_(_sqlQueryAttribute.ID)
|
|
1282 .ldc_i4_(++_uniqueQueryID)
|
|
1283 ;
|
|
1284 }
|
|
1285
|
|
1286 if (_sqlQueryAttribute.IsDynamic)
|
|
1287 {
|
|
1288 Type attrType = typeof(SqlQueryAttribute);
|
|
1289 FieldBuilder field = Context.CreatePrivateStaticField(attrType + "$" + ++_nameCounter, attrType);
|
|
1290 Label isNull = emit.DefineLabel();
|
|
1291
|
|
1292 emit
|
|
1293 .ldsfld(field)
|
|
1294 .brtrue_s(isNull)
|
|
1295
|
|
1296 .ldarg_0
|
|
1297 .call(typeof(MethodBase), "GetCurrentMethod")
|
|
1298 .castclass(typeof(MethodInfo))
|
|
1299 .callvirt(_baseType, "GetSqlQueryAttribute", _bindingFlags, typeof(MethodInfo))
|
|
1300
|
|
1301 .stsfld(field)
|
|
1302 .MarkLabel(isNull)
|
|
1303
|
|
1304 .ldsfld(field)
|
|
1305 .ldarg_0
|
|
1306 .ldloc(_locManager)
|
|
1307 .callvirt(attrType, "GetSqlText", _bindingFlags, typeof(DataAccessor), typeof(DbManager))
|
|
1308 ;
|
|
1309 }
|
|
1310 else
|
|
1311 {
|
|
1312 emit
|
|
1313 .ldstr(_sqlQueryAttribute.SqlText)
|
|
1314 ;
|
|
1315 }
|
|
1316
|
|
1317 if (_sqlQueryAttribute.ID != int.MinValue)
|
|
1318 {
|
|
1319 emit
|
|
1320 .callvirt(_baseType, "PrepareSqlQuery", _bindingFlags,
|
|
1321 typeof(DbManager), typeof(int), typeof(int), typeof(string))
|
|
1322 ;
|
|
1323 }
|
|
1324 }
|
|
1325 else
|
|
1326 {
|
|
1327 object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(SprocNameAttribute), true);
|
|
1328
|
|
1329 if (attrs.Length == 0)
|
|
1330 {
|
|
1331 attrs = Context.CurrentMethod.GetCustomAttributes(typeof(ActionNameAttribute), true);
|
|
1332
|
|
1333 string actionName = attrs.Length == 0 ?
|
|
1334 Context.CurrentMethod.Name : ((ActionNameAttribute)attrs[0]).Name;
|
|
1335
|
|
1336 // Call GetSpName.
|
|
1337 //
|
|
1338 emit
|
|
1339 .ldloc(_locManager)
|
|
1340 .ldarg_0
|
|
1341 .ldloc(_locObjType)
|
|
1342 .ldstr(actionName)
|
|
1343 .callvirt(_baseType, "GetSpName", _bindingFlags, typeof(Type), typeof(string))
|
|
1344 ;
|
|
1345 }
|
|
1346 else
|
|
1347 {
|
|
1348 emit
|
|
1349 .ldloc(_locManager)
|
|
1350 .ldstr(((SprocNameAttribute)attrs[0]).Name)
|
|
1351 ;
|
|
1352 }
|
|
1353 }
|
|
1354
|
|
1355 // string.Format
|
|
1356 //
|
|
1357 if (_formatParamList.Count > 0)
|
|
1358 {
|
|
1359 emit
|
|
1360 .ldc_i4_(_formatParamList.Count)
|
|
1361 .newarr(typeof(object))
|
|
1362 ;
|
|
1363
|
|
1364 for (int i = 0; i < _formatParamList.Count; i++)
|
|
1365 {
|
|
1366 ParameterInfo pi = (ParameterInfo)_formatParamList[i];
|
|
1367
|
|
1368 emit
|
|
1369 .dup
|
|
1370 .ldc_i4_(i)
|
|
1371 .ldarg(pi)
|
|
1372 .boxIfValueType(pi.ParameterType)
|
|
1373 .stelem_ref
|
|
1374 .end()
|
|
1375 ;
|
|
1376 }
|
|
1377
|
|
1378 emit
|
|
1379 .call(typeof(string), "Format", typeof(string), typeof(object[]))
|
|
1380 ;
|
|
1381 }
|
|
1382 }
|
|
1383
|
|
1384 void CallSetCommand()
|
|
1385 {
|
|
1386 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1387
|
|
1388 // Get DiscoverParametersAttribute.
|
|
1389 //
|
|
1390 object[] attrs =
|
|
1391 Context.CurrentMethod.DeclaringType.GetCustomAttributes(typeof(DiscoverParametersAttribute), true);
|
|
1392
|
|
1393 bool discoverParams = false;
|
|
1394
|
|
1395 if (_sqlQueryAttribute == null)
|
|
1396 {
|
|
1397 discoverParams = attrs.Length == 0 ?
|
|
1398 false : ((DiscoverParametersAttribute)attrs[0]).Discover;
|
|
1399
|
|
1400 attrs = Context.CurrentMethod.GetCustomAttributes(typeof(DiscoverParametersAttribute), true);
|
|
1401
|
|
1402 if (attrs.Length != 0)
|
|
1403 discoverParams = ((DiscoverParametersAttribute)attrs[0]).Discover;
|
|
1404 }
|
|
1405
|
|
1406 LocalBuilder locParams = discoverParams ?
|
|
1407 BuildParametersWithDiscoverParameters() :
|
|
1408 BuildParameters();
|
|
1409
|
|
1410 // Call SetSpCommand.
|
|
1411 //
|
|
1412 string methodName = _sqlQueryAttribute == null ? "SetSpCommand" : "SetCommand";
|
|
1413 Type paramType = _sqlQueryAttribute == null ? typeof(object[]) : typeof(IDbDataParameter[]);
|
|
1414
|
|
1415 emit
|
|
1416 .ldloc(locParams)
|
|
1417 .callvirt(typeof(DbManager), methodName, _bindingFlags, typeof(string), paramType)
|
|
1418 ;
|
|
1419 }
|
|
1420
|
|
1421 LocalBuilder BuildParameters()
|
|
1422 {
|
|
1423 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1424
|
|
1425 LocalBuilder retParams = emit
|
|
1426 .DeclareLocal(typeof(IDbDataParameter[]));
|
|
1427
|
|
1428 LocalBuilder locParams = _refParamList.Count > 0 ?
|
|
1429 BuildRefParameters() :
|
|
1430 BuildSimpleParameters();
|
|
1431
|
|
1432 emit
|
|
1433 .ldarg_0
|
|
1434 .ldloc(_locManager)
|
|
1435 .ldloc(locParams)
|
|
1436 .callvirt(_baseType, "PrepareParameters", _bindingFlags, typeof(DbManager), typeof(object[]))
|
|
1437 .stloc(retParams)
|
|
1438 ;
|
|
1439
|
|
1440 return retParams;
|
|
1441 }
|
|
1442
|
|
1443 LocalBuilder BuildSimpleParameters()
|
|
1444 {
|
|
1445 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1446
|
|
1447 // Parameters.
|
|
1448 //
|
|
1449 LocalBuilder locParams = emit.DeclareLocal(
|
|
1450 _sqlQueryAttribute == null ? typeof(object[]) : typeof(IDbDataParameter[]));
|
|
1451
|
|
1452 emit
|
|
1453 .ldc_i4_(_paramList.Count)
|
|
1454 .newarr(_sqlQueryAttribute == null ? typeof(object) : typeof(IDbDataParameter))
|
|
1455 ;
|
|
1456
|
|
1457 for (int i = 0; i < _paramList.Count; i++)
|
|
1458 {
|
|
1459 ParameterInfo pi = (ParameterInfo)_paramList[i];
|
|
1460
|
|
1461 emit
|
|
1462 .dup
|
|
1463 .ldc_i4_(i)
|
|
1464 ;
|
|
1465
|
|
1466 BuildParameter(pi);
|
|
1467
|
|
1468 emit
|
|
1469 .stelem_ref
|
|
1470 .end()
|
|
1471 ;
|
|
1472 }
|
|
1473
|
|
1474 emit.stloc(locParams);
|
|
1475 return locParams;
|
|
1476 }
|
|
1477
|
|
1478 FieldBuilder CreateStringArrayField(object[] attrs)
|
|
1479 {
|
|
1480 if (attrs.Length == 0)
|
|
1481 return null;
|
|
1482
|
|
1483 List<string> list = new List<string>();
|
|
1484
|
|
1485 foreach (Direction attr in attrs)
|
|
1486 if (attr.Members != null)
|
|
1487 list.AddRange(attr.Members);
|
|
1488
|
|
1489 if (list.Count == 0)
|
|
1490 return null;
|
|
1491
|
|
1492 list.Sort(string.CompareOrdinal);
|
|
1493
|
|
1494 string[] strings = list.ToArray();
|
|
1495
|
|
1496 // There a no limit for a field name length, but Visual Studio Debugger
|
|
1497 // may crash on fields with name longer then 256 symbols.
|
|
1498 //
|
|
1499 string key = "_string_array$" + string.Join("%", strings);
|
|
1500 FieldBuilder fieldBuilder = Context.GetField(key);
|
|
1501
|
|
1502 if (null == fieldBuilder)
|
|
1503 {
|
|
1504 fieldBuilder = Context.CreatePrivateStaticField(key, typeof(string[]));
|
|
1505
|
|
1506 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
|
|
1507
|
|
1508 emit
|
|
1509 .ldc_i4_(strings.Length)
|
|
1510 .newarr(typeof(string))
|
|
1511 ;
|
|
1512
|
|
1513 for (int i = 0; i < strings.Length; i++)
|
|
1514 {
|
|
1515 emit
|
|
1516 .dup
|
|
1517 .ldc_i4_(i)
|
|
1518 .ldstr(strings[i])
|
|
1519 .stelem_ref
|
|
1520 .end()
|
|
1521 ;
|
|
1522 }
|
|
1523
|
|
1524 emit
|
|
1525 .stsfld(fieldBuilder)
|
|
1526 ;
|
|
1527 }
|
|
1528
|
|
1529 return fieldBuilder;
|
|
1530 }
|
|
1531
|
|
1532 FieldBuilder CreateNullValueField(Type type, string value)
|
|
1533 {
|
|
1534 string key = "_null_value$" + type.FullName + "%" + value;
|
|
1535 FieldBuilder fieldBuilder = Context.GetField(key);
|
|
1536
|
|
1537 if (null == fieldBuilder)
|
|
1538 {
|
|
1539 fieldBuilder = Context.CreatePrivateStaticField(key, type);
|
|
1540
|
|
1541 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
|
|
1542
|
|
1543 emit
|
|
1544 .LoadType(type)
|
|
1545 .call(typeof(TypeDescriptor), "GetConverter", typeof(Type))
|
|
1546 .ldstr(value)
|
|
1547 .callvirt(typeof(TypeConverter), "ConvertFromInvariantString", typeof(string))
|
|
1548 .unbox_any(type)
|
|
1549 .stsfld(fieldBuilder)
|
|
1550 ;
|
|
1551 }
|
|
1552
|
|
1553 return fieldBuilder;
|
|
1554 }
|
|
1555
|
|
1556 LocalBuilder BuildRefParameters()
|
|
1557 {
|
|
1558 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1559
|
|
1560 // Parameters.
|
|
1561 //
|
|
1562 LocalBuilder locParams = emit.DeclareLocal(typeof(object[]));
|
|
1563
|
|
1564 emit
|
|
1565 .ldc_i4_(_parameters.Length)
|
|
1566 .newarr(typeof(object))
|
|
1567 ;
|
|
1568
|
|
1569 for (int i = 0; i < _parameters.Length; i++)
|
|
1570 {
|
|
1571 ParameterInfo pi = _parameters[i];
|
|
1572
|
|
1573 emit
|
|
1574 .dup
|
|
1575 .ldc_i4_(i)
|
|
1576 ;
|
|
1577
|
|
1578 if (_paramList.Contains(pi))
|
|
1579 {
|
|
1580 BuildParameter(pi);
|
|
1581 }
|
|
1582 else if (_refParamList.Contains(pi))
|
|
1583 {
|
|
1584 var mapOutputParameters = false;
|
|
1585 string returnValueMember = null;
|
|
1586 FieldBuilder fieldBuilder;
|
|
1587 var type =
|
|
1588 pi.ParameterType == typeof(DataRow) || pi.ParameterType.IsSubclassOf(typeof(DataRow)) ?
|
|
1589 typeof(DataRow) : typeof(object);
|
|
1590
|
|
1591 emit
|
|
1592 .ldarg_0
|
|
1593 .ldloc(_locManager)
|
|
1594 .ldarg(pi)
|
|
1595 ;
|
|
1596
|
|
1597 fieldBuilder = CreateStringArrayField(pi.GetCustomAttributes(typeof(Direction.OutputAttribute), true));
|
|
1598
|
|
1599 if (fieldBuilder != null)
|
|
1600 {
|
|
1601 emit.ldsfld(fieldBuilder);
|
|
1602 mapOutputParameters = true;
|
|
1603 }
|
|
1604 else
|
|
1605 emit.ldnull.end();
|
|
1606
|
|
1607 fieldBuilder = CreateStringArrayField(pi.GetCustomAttributes(typeof(Direction.InputOutputAttribute), true));
|
|
1608
|
|
1609 if (fieldBuilder != null)
|
|
1610 {
|
|
1611 emit.ldsfld(fieldBuilder);
|
|
1612 mapOutputParameters = true;
|
|
1613 }
|
|
1614 else
|
|
1615 emit.ldnull.end();
|
|
1616
|
|
1617 fieldBuilder = CreateStringArrayField(pi.GetCustomAttributes(typeof(Direction.IgnoreAttribute), true));
|
|
1618
|
|
1619 if (fieldBuilder != null)
|
|
1620 emit.ldsfld(fieldBuilder);
|
|
1621 else
|
|
1622 emit.ldnull.end();
|
|
1623
|
|
1624 emit
|
|
1625 .ldnull
|
|
1626 .callvirt(_baseType, "CreateParameters", _bindingFlags,
|
|
1627 typeof(DbManager), type, typeof(string[]), typeof(string[]), typeof(string[]), typeof(IDbDataParameter[]))
|
|
1628 ;
|
|
1629
|
|
1630 object[] attrs = pi.GetCustomAttributes(typeof(Direction.ReturnValueAttribute), true);
|
|
1631
|
|
1632 if (attrs.Length != 0)
|
|
1633 returnValueMember = ((Direction.ReturnValueAttribute)attrs[0]).Member;
|
|
1634
|
|
1635 if (null != returnValueMember || mapOutputParameters)
|
|
1636 _mapOutputParameters.Add(new MapOutputParametersValue(returnValueMember, pi));
|
|
1637 }
|
|
1638 else
|
|
1639 {
|
|
1640 emit
|
|
1641 .ldnull
|
|
1642 .end()
|
|
1643 ;
|
|
1644 }
|
|
1645
|
|
1646 emit
|
|
1647 .stelem_ref
|
|
1648 .end()
|
|
1649 ;
|
|
1650 }
|
|
1651
|
|
1652 emit.stloc(locParams);
|
|
1653 return locParams;
|
|
1654 }
|
|
1655
|
|
1656 void LoadParameterOrNull(ParameterInfo pi, Type type)
|
|
1657 {
|
|
1658 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1659 object[] attrs = pi.GetCustomAttributes(typeof(ParamNullValueAttribute), true);
|
|
1660
|
|
1661 object nullValue = attrs.Length == 0 ?
|
|
1662 null : ((ParamNullValueAttribute)attrs[0]).Value;
|
|
1663
|
|
1664 Label labelNull = emit.DefineLabel();
|
|
1665 Label labelEndIf = emit.DefineLabel();
|
|
1666
|
|
1667 if (pi.Attributes == ParameterAttributes.Out)
|
|
1668 {
|
|
1669 emit
|
|
1670 .ldnull
|
|
1671 .end()
|
|
1672 ;
|
|
1673
|
|
1674 return;
|
|
1675 }
|
|
1676
|
|
1677 if (nullValue != null)
|
|
1678 {
|
|
1679 Type nullValueType = type;
|
|
1680 bool isNullable = TypeHelper.IsNullable(type);
|
|
1681
|
|
1682 if (type.IsEnum)
|
|
1683 {
|
|
1684 nullValueType = Enum.GetUnderlyingType(type);
|
|
1685 nullValue = System.Convert.ChangeType(nullValue, nullValueType);
|
|
1686 }
|
|
1687 else if (isNullable)
|
|
1688 {
|
|
1689 nullValueType = type.GetGenericArguments()[0];
|
|
1690
|
|
1691 emit
|
|
1692 .ldarga(pi)
|
|
1693 .call(type, "get_HasValue")
|
|
1694 .brfalse(labelNull)
|
|
1695 ;
|
|
1696 }
|
|
1697
|
|
1698 if (nullValueType == nullValue.GetType() && emit.LoadWellKnownValue(nullValue))
|
|
1699 {
|
|
1700 if (nullValueType == typeof(string))
|
|
1701 emit
|
|
1702 .ldargEx(pi, false)
|
|
1703 .call(nullValueType, "Equals", nullValueType)
|
|
1704 .brtrue(labelNull)
|
|
1705 ;
|
|
1706 else if (isNullable)
|
|
1707 emit
|
|
1708 .ldarga(pi)
|
|
1709 .call(type, "get_Value")
|
|
1710 .beq(labelNull)
|
|
1711 ;
|
|
1712 else
|
|
1713 emit
|
|
1714 .ldargEx(pi, false)
|
|
1715 .beq(labelNull)
|
|
1716 ;
|
|
1717 }
|
|
1718 else
|
|
1719 {
|
|
1720 string nullString = TypeDescriptor.GetConverter(nullValue).ConvertToInvariantString(nullValue);
|
|
1721 FieldBuilder staticField = CreateNullValueField(nullValueType, nullString);
|
|
1722 MethodInfo miEquals = new TypeHelper(nullValueType).GetPublicMethod("Equals", nullValueType);
|
|
1723
|
|
1724 if (miEquals == null)
|
|
1725 {
|
|
1726 // Is it possible?
|
|
1727 //
|
|
1728 throw new TypeBuilderException(string.Format(
|
|
1729 Resources.DataAccessorBuilder_EqualsMethodIsNotPublic, type.FullName));
|
|
1730 }
|
|
1731
|
|
1732 if (isNullable)
|
|
1733 emit
|
|
1734 .ldsflda(staticField)
|
|
1735 .ldarga(pi)
|
|
1736 .call(pi.ParameterType, "get_Value")
|
|
1737 ;
|
|
1738 else
|
|
1739 emit
|
|
1740 .ldsflda(staticField)
|
|
1741 .ldarg(pi)
|
|
1742 ;
|
|
1743
|
|
1744 if (miEquals.GetParameters()[0].ParameterType.IsClass)
|
|
1745 emit
|
|
1746 .boxIfValueType(nullValueType)
|
|
1747 ;
|
|
1748
|
|
1749 emit
|
|
1750 .call(miEquals)
|
|
1751 .brtrue(labelNull)
|
|
1752 ;
|
|
1753 }
|
|
1754 }
|
|
1755
|
|
1756 if (type.IsEnum)
|
|
1757 emit
|
|
1758 .ldloc(_locManager)
|
|
1759 .callvirt(typeof(DbManager).GetProperty("MappingSchema").GetGetMethod())
|
|
1760 ;
|
|
1761
|
|
1762 emit
|
|
1763 .ldargEx(pi, true)
|
|
1764 ;
|
|
1765
|
|
1766 if (type.IsEnum)
|
|
1767 emit
|
|
1768 .ldc_i4_1
|
|
1769 .callvirt(typeof(MappingSchema), "MapEnumToValue", typeof(object), typeof(bool))
|
|
1770 ;
|
|
1771
|
|
1772 if (nullValue != null)
|
|
1773 {
|
|
1774 emit
|
|
1775 .br(labelEndIf)
|
|
1776 .MarkLabel(labelNull)
|
|
1777 .ldnull
|
|
1778 .MarkLabel(labelEndIf)
|
|
1779 ;
|
|
1780 }
|
|
1781 }
|
|
1782
|
|
1783 void BuildParameter(ParameterInfo pi)
|
|
1784 {
|
|
1785 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1786 Type type = pi.ParameterType;
|
|
1787 object[] attrs = pi.GetCustomAttributes(typeof(ParamNameAttribute), true);
|
|
1788 string paramName = attrs.Length == 0 ? pi.Name : ((ParamNameAttribute)attrs[0]).Name;
|
|
1789
|
|
1790 ParameterDirection direction = !type.IsByRef ? ParameterDirection.Input :
|
|
1791 pi.IsOut ? ParameterDirection.Output : ParameterDirection.InputOutput;
|
|
1792
|
|
1793 emit
|
|
1794 .ldloc(_locManager)
|
|
1795 .ldc_i4_((int)direction)
|
|
1796 ;
|
|
1797
|
|
1798 if (paramName[0] != '@')
|
|
1799 {
|
|
1800 string methodName = _sqlQueryAttribute == null ? "GetSpParameterName" : "GetQueryParameterName";
|
|
1801 emit
|
|
1802 .ldarg_0
|
|
1803 .ldloc(_locManager)
|
|
1804 .ldstr(paramName)
|
|
1805 .callvirt(_baseType, methodName, _bindingFlags, typeof(DbManager), typeof(string))
|
|
1806 ;
|
|
1807 }
|
|
1808 else
|
|
1809 emit.ldstr(paramName);
|
|
1810
|
|
1811 if (type.IsByRef)
|
|
1812 {
|
|
1813 if (_outputParameters == null)
|
|
1814 _outputParameters = new ArrayList();
|
|
1815
|
|
1816 _outputParameters.Add(pi);
|
|
1817
|
|
1818 type = type.GetElementType();
|
|
1819 }
|
|
1820
|
|
1821 LoadParameterOrNull(pi, type);
|
|
1822
|
|
1823 // Special case for user-defined types.
|
|
1824 //
|
|
1825 attrs = pi.GetCustomAttributes(typeof(ParamTypeNameAttribute), true);
|
|
1826 if (attrs.Length > 0)
|
|
1827 {
|
|
1828 emit
|
|
1829 .ldstr(((ParamTypeNameAttribute)attrs[0]).TypeName)
|
|
1830 .callvirt(typeof(DbManager), "Parameter",
|
|
1831 typeof(ParameterDirection), typeof(string), typeof(object), typeof(string))
|
|
1832 ;
|
|
1833 }
|
|
1834 else
|
|
1835 {
|
|
1836 emit
|
|
1837 .callvirt(typeof(DbManager), "Parameter",
|
|
1838 typeof(ParameterDirection), typeof(string), typeof(object))
|
|
1839 ;
|
|
1840 }
|
|
1841
|
|
1842 // Check if parameter type/size is specified.
|
|
1843 //
|
|
1844 attrs = pi.GetCustomAttributes(typeof(ParamDbTypeAttribute), true);
|
|
1845 if (attrs.Length > 0)
|
|
1846 {
|
|
1847 emit
|
|
1848 .dup
|
|
1849 .ldc_i4_((int)((ParamDbTypeAttribute)attrs[0]).DbType)
|
|
1850 .callvirt(typeof(IDataParameter), "set_DbType", typeof(DbType))
|
|
1851 ;
|
|
1852 }
|
|
1853
|
|
1854 attrs = pi.GetCustomAttributes(typeof(ParamSizeAttribute), true);
|
|
1855 if (attrs.Length > 0)
|
|
1856 {
|
|
1857 emit
|
|
1858 .dup
|
|
1859 .ldc_i4_(((ParamSizeAttribute)attrs[0]).Size)
|
|
1860 .callvirt(typeof(IDbDataParameter), "set_Size", typeof(int))
|
|
1861 ;
|
|
1862 }
|
|
1863 }
|
|
1864
|
|
1865 LocalBuilder BuildParametersWithDiscoverParameters()
|
|
1866 {
|
|
1867 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1868 LocalBuilder locParams = emit.DeclareLocal(typeof(object[]));
|
|
1869
|
|
1870 emit
|
|
1871 .ldc_i4_(_paramList.Count)
|
|
1872 .newarr(typeof(object))
|
|
1873 ;
|
|
1874
|
|
1875 for (int i = 0; i < _paramList.Count; i++)
|
|
1876 {
|
|
1877 ParameterInfo pi = (ParameterInfo)_paramList[i];
|
|
1878
|
|
1879 emit
|
|
1880 .dup
|
|
1881 .ldc_i4_(i)
|
|
1882 ;
|
|
1883
|
|
1884 LoadParameterOrNull(pi, pi.ParameterType);
|
|
1885
|
|
1886 emit
|
|
1887 .stelem_ref
|
|
1888 .end()
|
|
1889 ;
|
|
1890 }
|
|
1891
|
|
1892 emit.stloc(locParams);
|
|
1893 return locParams;
|
|
1894 }
|
|
1895
|
|
1896 void StoreParameterValue(LocalBuilder param, ParameterInfo pi, Type type)
|
|
1897 {
|
|
1898 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
1899 Label labelNull = emit.DefineLabel();
|
|
1900 Label labelEndIf = emit.DefineLabel();
|
|
1901
|
|
1902 object[] attrs = pi.GetCustomAttributes(typeof(ParamNullValueAttribute), true);
|
|
1903 object nullValue = attrs.Length == 0 ? null : ((ParamNullValueAttribute)attrs[0]).Value;
|
|
1904
|
|
1905 if (nullValue != null)
|
|
1906 {
|
|
1907 emit
|
|
1908 .ldarg_0
|
|
1909 .ldloc(_locManager)
|
|
1910 .ldloc(param)
|
|
1911 .callvirt(typeof(IDataParameter).GetProperty("Value").GetGetMethod())
|
|
1912 .ldloc(param)
|
|
1913 .callvirt(_baseType, "IsNull", _bindingFlags, typeof(DbManager), typeof(object), typeof(object))
|
|
1914 .brtrue(labelNull)
|
|
1915 ;
|
|
1916 }
|
|
1917
|
|
1918 if (type.IsEnum)
|
|
1919 {
|
|
1920 emit
|
|
1921 .ldloc(_locManager)
|
|
1922 .callvirt(typeof(DbManager).GetProperty("MappingSchema").GetGetMethod())
|
|
1923 .ldloc(param)
|
|
1924 .callvirt(typeof(IDataParameter).GetProperty("Value").GetGetMethod())
|
|
1925 .LoadType(type)
|
|
1926 .callvirt(typeof(MappingSchema), "MapValueToEnum", typeof(object), typeof(Type))
|
|
1927 .CastFromObject(type)
|
|
1928 ;
|
|
1929 }
|
|
1930 #if FW4
|
|
1931 else if (pi.IsRefCursor())
|
|
1932 {
|
|
1933 // Make sure the parameter is a List
|
|
1934 if (!type.GetInterfaces().Contains(typeof(IList)))
|
|
1935 {
|
|
1936 throw new Exception("The argument '" + pi.Name + "' must be of type 'IList'");
|
|
1937 }
|
|
1938 //Get the generic type of the list
|
|
1939 Type genericType = type.GetGenericArguments().First();
|
|
1940
|
|
1941
|
|
1942 // Get the data reader to the ref cursor
|
|
1943 var dataReader = emit.DeclareLocal(typeof(IDataReader));
|
|
1944 emit
|
|
1945 .ldloc(_locManager)
|
|
1946 .callvirt(typeof(DbManager).GetProperty("DataProvider").GetGetMethod())
|
|
1947 .ldloc(param)
|
|
1948 .callvirt(typeof(IDataParameter).GetProperty("Value").GetGetMethod())
|
|
1949 .callvirt(typeof(DataProviderBase), "GetRefCursorDataReader", typeof(object))
|
|
1950 .CastFromObject(typeof(IDataReader))
|
|
1951 .stloc(dataReader)
|
|
1952 ;
|
|
1953
|
|
1954 // Create the generic methos info to invoke
|
|
1955 var mapDataReaderToListMethodInfo = typeof (MappingSchema).GetMethod("MapDataReaderToList",
|
|
1956 new[]
|
|
1957 {
|
|
1958 typeof (IDataReader),
|
|
1959 typeof (object[])
|
|
1960 })
|
|
1961 .MakeGenericMethod(genericType);
|
|
1962
|
|
1963 // Run MapDataReaderToList
|
|
1964 emit
|
|
1965 .ldloc(_locManager)
|
|
1966 .callvirt(typeof(DbManager).GetProperty("MappingSchema").GetGetMethod())
|
|
1967 .ldloc(dataReader)
|
|
1968 .ldnull
|
|
1969 .callvirt(mapDataReaderToListMethodInfo)
|
|
1970 ;
|
|
1971 }
|
|
1972 #endif
|
|
1973 else
|
|
1974 {
|
|
1975 emit
|
|
1976 .ldarg_0
|
|
1977 .ldloc(_locManager)
|
|
1978 .ldloc(param)
|
|
1979 .callvirt(typeof(IDataParameter).GetProperty("Value").GetGetMethod())
|
|
1980 ;
|
|
1981
|
|
1982 MethodInfo converter = GetConverterMethod(type);
|
|
1983
|
|
1984 if (converter == null)
|
|
1985 {
|
|
1986 emit
|
|
1987 .LoadType(type)
|
|
1988 .ldloc(param)
|
|
1989 .callvirt(_baseType, "ConvertChangeType", _bindingFlags, typeof(DbManager), typeof(object), typeof(Type), typeof(object))
|
|
1990 .unboxIfValueType(type)
|
|
1991 ;
|
|
1992 }
|
|
1993 else
|
|
1994 {
|
|
1995 emit
|
|
1996 .ldloc(param)
|
|
1997 .callvirt(converter)
|
|
1998 ;
|
|
1999 }
|
|
2000 }
|
|
2001
|
|
2002 if (nullValue != null)
|
|
2003 {
|
|
2004 emit
|
|
2005 .br(labelEndIf)
|
|
2006 .MarkLabel(labelNull);
|
|
2007
|
|
2008 if (nullValue.GetType() != type || !emit.LoadWellKnownValue(nullValue))
|
|
2009 {
|
|
2010 string nullString = TypeDescriptor.GetConverter(type).ConvertToInvariantString(nullValue);
|
|
2011 FieldBuilder staticField = CreateNullValueField(type, nullString);
|
|
2012
|
|
2013 emit
|
|
2014 .ldsfld(staticField)
|
|
2015 ;
|
|
2016 }
|
|
2017
|
|
2018 emit
|
|
2019 .MarkLabel(labelEndIf)
|
|
2020 ;
|
|
2021 }
|
|
2022
|
|
2023 emit.stind(type);
|
|
2024 }
|
|
2025
|
|
2026 void GetOutRefParameters()
|
|
2027 {
|
|
2028 EmitHelper emit = Context.MethodBuilder.Emitter;
|
|
2029
|
|
2030 if (_outputParameters != null)
|
|
2031 {
|
|
2032 LocalBuilder param = emit.DeclareLocal(typeof(IDataParameter));
|
|
2033
|
|
2034 foreach (ParameterInfo pi in _outputParameters)
|
|
2035 {
|
|
2036 Type type = pi.ParameterType.GetElementType();
|
|
2037
|
|
2038 emit
|
|
2039 .ldarg(pi)
|
|
2040 ;
|
|
2041
|
|
2042 // Get parameter.
|
|
2043 //
|
|
2044 object[] attrs = pi.GetCustomAttributes(typeof(ParamNameAttribute), true);
|
|
2045
|
|
2046 string paramName = attrs.Length == 0 ?
|
|
2047 pi.Name : ((ParamNameAttribute)attrs[0]).Name;
|
|
2048
|
|
2049 emit
|
|
2050 .ldarg_0
|
|
2051 .ldloc(_locManager)
|
|
2052 ;
|
|
2053
|
|
2054 if (paramName[0] != '@')
|
|
2055 {
|
|
2056 string methodName = _sqlQueryAttribute == null ? "GetSpParameterName" : "GetQueryParameterName";
|
|
2057
|
|
2058 emit
|
|
2059 .ldarg_0
|
|
2060 .ldloc(_locManager)
|
|
2061 .ldstr(paramName)
|
|
2062 .callvirt(_baseType, methodName, _bindingFlags, typeof(DbManager), typeof(string))
|
|
2063 ;
|
|
2064 }
|
|
2065 else
|
|
2066 emit.ldstr(paramName);
|
|
2067
|
|
2068 emit
|
|
2069 .callvirt(_baseType, "GetParameter", _bindingFlags, typeof(DbManager), typeof(string))
|
|
2070 .stloc(param)
|
|
2071 ;
|
|
2072
|
|
2073 StoreParameterValue(param, pi, type);
|
|
2074 }
|
|
2075 }
|
|
2076
|
|
2077 foreach (MapOutputParametersValue v in _mapOutputParameters)
|
|
2078 {
|
|
2079 emit
|
|
2080 .ldloc(_locManager)
|
|
2081 .ldstrEx(v.ReturnValueMember)
|
|
2082 .ldarg(v.ParameterInfo)
|
|
2083 .callvirt(typeof(DbManager), "MapOutputParameters", typeof(string), typeof(object));
|
|
2084 }
|
|
2085 }
|
|
2086
|
|
2087 static bool IsInterfaceOf(Type type, Type interfaceType)
|
|
2088 {
|
|
2089 Type[] types = type.GetInterfaces();
|
|
2090
|
|
2091 foreach (Type t in types)
|
|
2092 if (t == interfaceType)
|
|
2093 return true;
|
|
2094
|
|
2095 return type == interfaceType;
|
|
2096 }
|
|
2097
|
|
2098 private MethodInfo GetConverterMethod(Type type)
|
|
2099 {
|
|
2100 if (type.IsEnum)
|
|
2101 type = Enum.GetUnderlyingType(type);
|
|
2102
|
|
2103 Type[] types = new Type[] { typeof(DbManager), typeof(object), typeof(object) };
|
|
2104 return _baseType.GetMethod("ConvertTo" + type.Name, _bindingFlags, null, types, null);
|
|
2105 }
|
|
2106 }
|
|
2107 }
|