comparison Source/Reflection/MetadataProvider/AttributeMetadataProvider.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f990fcb411a9
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Reflection;
5 using BLToolkit.Data.Sql.SqlProvider;
6
7 using BLToolkit.TypeBuilder;
8
9 namespace BLToolkit.Reflection.MetadataProvider
10 {
11 using DataAccess;
12 using Extension;
13 using Mapping;
14
15 public class AttributeMetadataProvider : MetadataProviderBase
16 {
17 #region Helpers
18
19 private TypeAccessor _typeAccessor;
20 private object[] _mapFieldAttributes;
21 private object[] _nonUpdatableAttributes;
22 readonly object _sync = new object();
23
24 void EnsureMapper(TypeAccessor typeAccessor)
25 {
26 if (_typeAccessor != typeAccessor)
27 {
28 _typeAccessor = typeAccessor;
29 _mapFieldAttributes = null;
30 _nonUpdatableAttributes = null;
31 }
32 }
33
34 protected object[] GetMapFieldAttributes(TypeAccessor typeAccessor)
35 {
36 lock (_sync)
37 {
38 EnsureMapper(typeAccessor);
39
40 return _mapFieldAttributes ?? (_mapFieldAttributes = TypeHelper.GetAttributes(typeAccessor.Type, typeof (MapFieldAttribute)));
41 }
42 }
43
44 object[] GetNonUpdatableAttributes(TypeAccessor typeAccessor)
45 {
46 lock (_sync)
47 {
48 EnsureMapper(typeAccessor);
49
50 return _nonUpdatableAttributes ?? (_nonUpdatableAttributes = TypeHelper.GetAttributes(typeAccessor.Type, typeof(NonUpdatableAttribute)));
51 }
52 }
53
54 #endregion
55
56 #region GetFieldName
57
58 public override string GetFieldName(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
59 {
60 var a = member.GetAttribute<MapFieldAttribute>();
61
62 if (a != null && a.MapName != null)
63 {
64 isSet = true;
65 return a.MapName;
66 }
67
68 foreach (MapFieldAttribute attr in GetMapFieldAttributes(member.TypeAccessor))
69 {
70 if (attr.MapName != null && string.Equals(attr.OrigName, member.Name, StringComparison.InvariantCultureIgnoreCase))
71 {
72 isSet = true;
73 return attr.MapName;
74 }
75 }
76
77 return base.GetFieldName(typeExtension, member, out isSet);
78 }
79
80 #endregion
81
82 #region GetFieldStorage
83
84 public override string GetFieldStorage(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
85 {
86 var a = member.GetAttribute<MapFieldAttribute>();
87
88 if (a != null)
89 {
90 isSet = true;
91 return a.Storage;
92 }
93
94 foreach (MapFieldAttribute attr in GetMapFieldAttributes(member.TypeAccessor))
95 {
96 if (string.Equals(attr.OrigName, member.Name, StringComparison.InvariantCultureIgnoreCase))
97 {
98 isSet = true;
99 return attr.Storage;
100 }
101 }
102
103 return base.GetFieldStorage(typeExtension, member, out isSet);
104 }
105
106 #endregion
107
108 #region GetInheritanceDiscriminator
109
110 public override bool GetInheritanceDiscriminator(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
111 {
112 var a = member.GetAttribute<MapFieldAttribute>();
113
114 if (a != null)
115 {
116 isSet = true;
117 return a.IsInheritanceDiscriminator;
118 }
119
120 foreach (MapFieldAttribute attr in GetMapFieldAttributes(member.TypeAccessor))
121 {
122 if (string.Equals(attr.OrigName, member.Name, StringComparison.InvariantCultureIgnoreCase))
123 {
124 isSet = true;
125 return attr.IsInheritanceDiscriminator;
126 }
127 }
128
129 return base.GetInheritanceDiscriminator(typeExtension, member, out isSet);
130 }
131
132 #endregion
133
134 #region EnsureMapper
135
136 public override void EnsureMapper(TypeAccessor typeAccessor, MappingSchema mappingSchema, EnsureMapperHandler handler)
137 {
138 foreach (MapFieldAttribute attr in GetMapFieldAttributes(typeAccessor))
139 {
140 if (attr.OrigName != null)
141 handler(attr.MapName, attr.OrigName);
142 else
143 {
144 var ma = typeAccessor[attr.MapName];
145
146 foreach (MemberMapper inner in mappingSchema.GetObjectMapper(ma.Type))
147 handler(string.Format(attr.Format, inner.Name), ma.Name + "." + inner.MemberName);
148 }
149 }
150 }
151
152 #endregion
153
154 #region GetMapIgnore
155
156 public override bool GetMapIgnore(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
157 {
158 var attr = member.GetAttribute<MapIgnoreAttribute>() ?? (MapIgnoreAttribute)TypeHelper.GetFirstAttribute(member.Type, typeof(MapIgnoreAttribute));
159
160 if (attr != null)
161 {
162 isSet = true;
163 return attr.Ignore;
164 }
165
166 if (member.GetAttribute<MapFieldAttribute>() != null ||
167 member.GetAttribute<MapImplicitAttribute>() != null ||
168 TypeHelper.GetFirstAttribute(member.Type, typeof(MapImplicitAttribute)) != null)
169 {
170 isSet = true;
171 return false;
172 }
173
174 return base.GetMapIgnore(typeExtension, member, out isSet) || member.GetAttribute<AssociationAttribute>() != null;
175 }
176
177 #endregion
178
179 #region GetMapField
180
181 public override MapFieldAttribute GetMapField(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
182 {
183 var attr = member.GetAttribute<MapFieldAttribute>() ?? (MapFieldAttribute)TypeHelper.GetFirstAttribute(member.Type, typeof(MapFieldAttribute));
184
185 if (attr != null)
186 {
187 isSet = true;
188 return attr;
189 }
190
191 return base.GetMapField(typeExtension, member, out isSet);
192 }
193
194 #endregion
195
196 #region GetDbType
197
198 [CLSCompliant(false)]
199 public override DbTypeAttribute GetDbType(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
200 {
201 var attr = member.GetAttribute<DbTypeAttribute>() ?? (DbTypeAttribute)TypeHelper.GetFirstAttribute(member.Type, typeof(DbTypeAttribute));
202
203 if (attr != null)
204 {
205 isSet = true;
206 return attr;
207 }
208
209 return base.GetDbType(typeExtension, member, out isSet);
210 }
211
212 #endregion
213
214 #region GetPrimaryKey
215
216 public override PrimaryKeyAttribute GetPrimaryKey(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
217 {
218 var attr = member.GetAttribute<PrimaryKeyAttribute>() ?? (PrimaryKeyAttribute)TypeHelper.GetFirstAttribute(member.Type, typeof(PrimaryKeyAttribute));
219
220 if (attr != null)
221 {
222 isSet = true;
223 return attr;
224 }
225
226 return base.GetPrimaryKey(typeExtension, member, out isSet);
227 }
228
229 #endregion
230
231 #region GetTrimmable
232
233 public override bool GetTrimmable(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
234 {
235 if (member.Type == typeof(string))
236 {
237 var attr = member.GetAttribute<TrimmableAttribute>();
238
239 if (attr != null)
240 {
241 isSet = true;
242 return attr.IsTrimmable;
243 }
244
245 attr = (TrimmableAttribute)TypeHelper.GetFirstAttribute(
246 member.MemberInfo.DeclaringType, typeof(TrimmableAttribute));
247
248 if (attr != null)
249 {
250 isSet = true;
251 return attr.IsTrimmable;
252 }
253 }
254
255 return base.GetTrimmable(typeExtension, member, out isSet);
256 }
257
258 #endregion
259
260 #region GetMapValues
261
262 public override MapValue[] GetMapValues(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
263 {
264 List<MapValue> list = null;
265
266 object[] attrs = member.GetAttributes<MapValueAttribute>();
267
268 if (attrs != null)
269 {
270 list = new List<MapValue>(attrs.Length);
271
272 foreach (MapValueAttribute a in attrs)
273 list.Add(new MapValue(a.OrigValue, a.Values));
274 }
275
276 attrs = member.GetTypeAttributes(typeof(MapValueAttribute));
277
278 var memberType = TypeHelper.UnwrapNullableType(member.Type);
279
280 if (attrs != null && attrs.Length > 0)
281 {
282 if (list == null)
283 list = new List<MapValue>(attrs.Length);
284
285 foreach (MapValueAttribute a in attrs)
286 if (a.Type == null && a.OrigValue != null && a.OrigValue.GetType() == memberType ||
287 a.Type is Type && (Type)a.Type == memberType)
288 list.Add(new MapValue(a.OrigValue, a.Values));
289 }
290
291 var typeMapValues = GetMapValues(typeExtension, memberType, out isSet);
292
293 if (list == null)
294 return typeMapValues;
295
296 if (typeMapValues != null)
297 list.AddRange(typeMapValues);
298
299 isSet = true;
300
301 return list.ToArray();
302 }
303
304 const FieldAttributes EnumField = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
305
306 static List<MapValue> GetEnumMapValues(Type type)
307 {
308 var list = null as List<MapValue>;
309 var fields = type.GetFields();
310
311 foreach (var fi in fields)
312 {
313 if ((fi.Attributes & EnumField) == EnumField)
314 {
315 var enumAttributes = Attribute.GetCustomAttributes(fi, typeof(MapValueAttribute));
316
317 foreach (MapValueAttribute attr in enumAttributes)
318 {
319 if (list == null)
320 list = new List<MapValue>(fields.Length);
321
322 var origValue = Enum.Parse(type, fi.Name, false);
323
324 list.Add(new MapValue(origValue, attr.Values));
325 }
326 }
327 }
328
329 return list;
330 }
331
332 public override MapValue[] GetMapValues(TypeExtension typeExtension, Type type, out bool isSet)
333 {
334 List<MapValue> list = null;
335
336 if (TypeHelper.IsNullable(type))
337 type = type.GetGenericArguments()[0];
338
339 if (type.IsEnum)
340 list = GetEnumMapValues(type);
341
342 var attrs = TypeHelper.GetAttributes(type, typeof(MapValueAttribute));
343
344 if (attrs != null && attrs.Length != 0)
345 {
346 if (list == null)
347 list = new List<MapValue>(attrs.Length);
348
349 for (var i = 0; i < attrs.Length; i++)
350 {
351 var a = (MapValueAttribute)attrs[i];
352 list.Add(new MapValue(a.OrigValue, a.Values));
353 }
354 }
355
356 isSet = list != null;
357
358 return isSet? list.ToArray(): null;
359 }
360
361 #endregion
362
363 #region GetDefaultValue
364
365 public override object GetDefaultValue(MappingSchema mappingSchema, TypeExtension typeExtension, MemberAccessor member, out bool isSet)
366 {
367 // Check member [DefaultValue(0)]
368 //
369 var attr = member.GetAttribute<DefaultValueAttribute>();
370
371 if (attr != null)
372 {
373 isSet = true;
374 return attr.Value;
375 }
376
377 // Check type [DefaultValues(typeof(int), 0)]
378 //
379 var attrs = member.GetTypeAttributes(typeof(DefaultValueAttribute));
380
381 foreach (DefaultValueAttribute a in attrs)
382 if (a.Type == null && a.Value != null && a.Value.GetType() == member.Type ||
383 a.Type != null && a.Type == member.Type)
384 {
385 isSet = true;
386 return a.Value;
387 }
388
389 return GetDefaultValue(mappingSchema, typeExtension, member.Type, out isSet);
390 }
391
392 public override object GetDefaultValue(MappingSchema mappingSchema, TypeExtension typeExtension, Type type, out bool isSet)
393 {
394 object value = null;
395
396 if (type.IsEnum)
397 value = GetEnumDefaultValueFromType(type);
398
399 if (value == null)
400 {
401 var attrs = TypeHelper.GetAttributes(type, typeof(DefaultValueAttribute));
402
403 if (attrs != null && attrs.Length != 0)
404 value = ((DefaultValueAttribute)attrs[0]).Value;
405 }
406
407 isSet = value != null;
408
409 return TypeExtension.ChangeType(value, type);
410 }
411
412 private static object GetEnumDefaultValueFromType(Type type)
413 {
414 var fields = type.GetFields();
415
416 foreach (var fi in fields)
417 {
418 if ((fi.Attributes & EnumField) == EnumField)
419 {
420 var attrs = Attribute.GetCustomAttributes(fi, typeof(DefaultValueAttribute));
421
422 if (attrs.Length > 0)
423 return Enum.Parse(type, fi.Name, false);
424 }
425 }
426
427 return null;
428 }
429
430 #endregion
431
432 #region GetNullable
433
434 public override bool GetNullable(MappingSchema mappingSchema, TypeExtension typeExtension, MemberAccessor member, out bool isSet)
435 {
436 // Check member [Nullable(true | false)]
437 //
438 var attr1 = member.GetAttribute<NullableAttribute>();
439
440 if (attr1 != null)
441 {
442 isSet = true;
443 return attr1.IsNullable;
444 }
445
446 // Check member [NullValue(0)]
447 //
448 var attr2 = member.GetAttribute<NullValueAttribute>();
449
450 if (attr2 != null)
451 return isSet = true;
452
453 // Check type [Nullable(true || false)]
454 //
455 attr1 = (NullableAttribute)TypeHelper.GetFirstAttribute(
456 member.MemberInfo.DeclaringType, typeof(NullableAttribute));
457
458 if (attr1 != null)
459 {
460 isSet = true;
461 return attr1.IsNullable;
462 }
463
464 // Check type [NullValues(typeof(int), 0)]
465 //
466 var attrs = member.GetTypeAttributes(typeof(NullValueAttribute));
467
468 foreach (NullValueAttribute a in attrs)
469 if (a.Type == null && a.Value != null && a.Value.GetType() == member.Type ||
470 a.Type != null && a.Type == member.Type)
471 return isSet = true;
472
473 if (member.Type.IsEnum)
474 return isSet = mappingSchema.GetNullValue(member.Type) != null;
475
476 if (member.Type.IsClass)
477 {
478 var pk = member.GetAttribute<PrimaryKeyAttribute>();
479
480 if (pk != null)
481 {
482 isSet = false;
483 return false;
484 }
485 }
486
487 return base.GetNullable(mappingSchema, typeExtension, member, out isSet);
488 }
489
490 #endregion
491
492 #region GetLazyInstance
493
494 public override bool GetLazyInstance(MappingSchema mappingSchema, TypeExtension typeExtension, MemberAccessor member, out bool isSet)
495 {
496 var attr1 = member.GetAttribute<LazyInstanceAttribute>();
497
498 if (attr1 != null)
499 {
500 isSet = true;
501 return attr1.IsLazy;
502 }
503
504 attr1 = (LazyInstanceAttribute)TypeHelper.GetFirstAttribute(member.MemberInfo.DeclaringType, typeof(LazyInstanceAttribute));
505
506 if (attr1 != null)
507 {
508 isSet = true;
509 return attr1.IsLazy;
510 }
511
512 return base.GetLazyInstance(mappingSchema, typeExtension, member, out isSet);
513 }
514
515 #endregion
516
517 #region GetNullValue
518
519 private static object CheckNullValue(object value, MemberAccessor member)
520 {
521 if (value is Type && (Type)value == typeof(DBNull))
522 {
523 value = DBNull.Value;
524
525 if (member.Type == typeof(string))
526 value = null;
527 }
528
529 return value;
530 }
531
532 public override object GetNullValue(MappingSchema mappingSchema, TypeExtension typeExtension, MemberAccessor member, out bool isSet)
533 {
534 // Check member [NullValue(0)]
535 //
536 var attr = member.GetAttribute<NullValueAttribute>();
537
538 if (attr != null)
539 {
540 isSet = true;
541 return CheckNullValue(attr.Value, member);
542 }
543
544 // Check type [NullValues(typeof(int), 0)]
545 //
546 var attrs = member.GetTypeAttributes(typeof(NullValueAttribute));
547
548 foreach (NullValueAttribute a in attrs)
549 {
550 if (a.Type == null && a.Value != null && a.Value.GetType() == member.Type ||
551 a.Type != null && a.Type == member.Type)
552 {
553 isSet = true;
554 return CheckNullValue(a.Value, member);
555 }
556 }
557
558 if (member.Type.IsEnum)
559 {
560 var value = CheckNullValue(mappingSchema.GetNullValue(member.Type), member);
561
562 if (value != null)
563 {
564 isSet = true;
565 return value;
566 }
567 }
568
569 isSet = false;
570 return null;
571 }
572
573 #endregion
574
575 #region GetDbName
576
577 public override string GetDatabaseName(Type type, ExtensionList extensions, out bool isSet)
578 {
579 var attrs = type.GetCustomAttributes(typeof(TableNameAttribute), true);
580
581 if (attrs.Length > 0)
582 {
583 var name = ((TableNameAttribute)attrs[0]).Database;
584 isSet = name != null;
585 return name;
586 }
587
588 return base.GetDatabaseName(type, extensions, out isSet);
589 }
590
591 #endregion
592
593 #region GetTableName
594
595 public override string GetOwnerName(Type type, ExtensionList extensions, out bool isSet)
596 {
597 var attrs = type.GetCustomAttributes(typeof(TableNameAttribute), true);
598
599 if (attrs.Length > 0)
600 {
601 var name = ((TableNameAttribute)attrs[0]).Owner;
602 isSet = name != null;
603 return name;
604 }
605
606 return base.GetOwnerName(type, extensions, out isSet);
607 }
608
609 #endregion
610
611 #region GetTableName
612
613 public override string GetTableName(Type type, ExtensionList extensions, out bool isSet)
614 {
615 var attrs = type.GetCustomAttributes(typeof(TableNameAttribute), true);
616
617 if (attrs.Length > 0)
618 {
619 var name = ((TableNameAttribute)attrs[0]).Name;
620 isSet = name != null;
621 return name;
622 }
623
624 return base.GetTableName(type, extensions, out isSet);
625 }
626
627 #endregion
628
629 #region GetPrimaryKeyOrder
630
631 public override int GetPrimaryKeyOrder(Type type, TypeExtension typeExt, MemberAccessor member, out bool isSet)
632 {
633 var attr = member.GetAttribute<PrimaryKeyAttribute>();
634
635 if (attr != null)
636 {
637 isSet = true;
638 return attr.Order;
639 }
640
641 return base.GetPrimaryKeyOrder(type, typeExt, member, out isSet);
642 }
643
644 #endregion
645
646 public override string GetSequenceName(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
647 {
648 var attr = member.GetAttribute<SequenceNameAttribute>();
649
650 if (attr != null)
651 {
652 isSet = true;
653 return attr.SequenceName;
654 }
655
656 return base.GetSequenceName(typeExtension, member, out isSet);
657 }
658
659 #region GetNonUpdatableFlag
660
661 public override NonUpdatableAttribute GetNonUpdatableAttribute(Type type, TypeExtension typeExt, MemberAccessor member, out bool isSet)
662 {
663 var attr = member.GetAttribute<NonUpdatableAttribute>();
664
665 if (attr != null)
666 {
667 isSet = true;
668 return attr;
669 }
670
671 foreach (NonUpdatableAttribute a in GetNonUpdatableAttributes(member.TypeAccessor))
672 {
673 if (string.Equals(a.FieldName, member.Name, StringComparison.InvariantCultureIgnoreCase))
674 {
675 isSet = true;
676 return a;
677 }
678 }
679
680 return base.GetNonUpdatableAttribute(type, typeExt, member, out isSet);
681 }
682
683 #endregion
684
685 #region GetSqlIgnore
686
687 public override bool GetSqlIgnore(TypeExtension typeExtension, MemberAccessor member, out bool isSet)
688 {
689 var attr = member.GetAttribute<SqlIgnoreAttribute>();
690
691 if (attr == null)
692 attr = (SqlIgnoreAttribute)TypeHelper.GetFirstAttribute(member.Type, typeof(SqlIgnoreAttribute));
693
694 if (attr != null)
695 {
696 isSet = true;
697 return attr.Ignore;
698 }
699
700 return base.GetSqlIgnore(typeExtension, member, out isSet);
701 }
702
703 #endregion
704
705 #region GetRelations
706
707 public override List<MapRelationBase> GetRelations(MappingSchema schema, ExtensionList typeExt, Type master, Type slave, out bool isSet)
708 {
709 var masterAccessor = TypeAccessor.GetAccessor(master);
710 var slaveAccessor = slave != null ? TypeAccessor.GetAccessor(slave) : null;
711 var relations = new List<MapRelationBase>();
712
713 foreach (MemberAccessor ma in masterAccessor)
714 {
715 var attr = ma.GetAttribute<RelationAttribute>();
716
717 if (attr == null || (slave != null && attr.Destination != slave && ma.Type != slave))
718 continue;
719
720 if (slave == null)
721 slaveAccessor = TypeAccessor.GetAccessor(attr.Destination ?? ma.Type);
722
723
724 var toMany = TypeHelper.IsSameOrParent(typeof(IEnumerable), ma.Type);
725
726 if (toMany && attr.Destination == null)
727 throw new InvalidOperationException("Destination type should be set for enumerable relations: " + ma.Type.FullName + "." + ma.Name);
728
729 var masterIndex = attr.MasterIndex;
730 var slaveIndex = attr.SlaveIndex;
731
732 if (slaveIndex == null)
733 {
734 var accessor = toMany ? masterAccessor : slaveAccessor;
735 var tex = TypeExtension.GetTypeExtension(accessor.Type, typeExt);
736 var keys = GetPrimaryKeyFields(schema, accessor, tex);
737
738 if (keys.Count > 0)
739 slaveIndex = new MapIndex(keys.ToArray());
740 }
741
742 if (slaveIndex == null)
743 throw new InvalidOperationException("Slave index is not set for relation: " + ma.Type.FullName + "." + ma.Name);
744
745 if (masterIndex == null)
746 masterIndex = slaveIndex;
747
748 var relation = new MapRelationBase(attr.Destination ?? ma.Type, slaveIndex, masterIndex, ma.Name);
749
750 relations.Add(relation);
751 }
752
753 isSet = true;
754 return relations;
755 }
756
757 #endregion
758
759 #region GetAssociation
760
761 public override Association GetAssociation(TypeExtension typeExtension, MemberAccessor member)
762 {
763 var aa = member.GetAttribute<AssociationAttribute>();
764
765 if (aa == null)
766 return base.GetAssociation(typeExtension, member);
767
768 return new Association(
769 member,
770 aa.GetThisKeys(),
771 aa.GetOtherKeys(),
772 aa.Storage,
773 aa.CanBeNull);
774 }
775
776 #endregion
777
778 #region GetInheritanceMapping
779
780 public override InheritanceMappingAttribute[] GetInheritanceMapping(Type type, TypeExtension typeExtension)
781 {
782 var attrs = type.GetCustomAttributes(typeof(InheritanceMappingAttribute), true);
783
784 if (attrs.Length > 0)
785 {
786 var maps = new InheritanceMappingAttribute[attrs.Length];
787
788 for (var i = 0; i < attrs.Length; i++)
789 maps[i] = (InheritanceMappingAttribute)attrs[i];
790
791 return maps;
792 }
793
794 return base.GetInheritanceMapping(type, typeExtension);
795 }
796
797 #endregion
798 }
799 }