Mercurial > pub > bltoolkit
comparison Source/Reflection/MetadataProvider/ExtensionMetadataProvider.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.Data; | |
5 using System.Linq; | |
6 using System.Reflection; | |
7 | |
8 using BLToolkit.Common; | |
9 using BLToolkit.DataAccess; | |
10 | |
11 using Convert=System.Convert; | |
12 | |
13 namespace BLToolkit.Reflection.MetadataProvider | |
14 { | |
15 using Extension; | |
16 using Mapping; | |
17 | |
18 public class ExtensionMetadataProvider : MetadataProviderBase | |
19 { | |
20 #region Helpers | |
21 | |
22 private static object GetValue(TypeExtension typeExtension, MemberAccessor member, string elemName, out bool isSet) | |
23 { | |
24 AttributeExtensionCollection ext; | |
25 isSet = typeExtension[member.Name].Attributes.TryGetValue(elemName, out ext); | |
26 return isSet ? ext.Value : null; | |
27 } | |
28 | |
29 #endregion | |
30 | |
31 #region GetFieldName | |
32 | |
33 public override string GetFieldName(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
34 { | |
35 var value = GetValue(typeExtension, member, "MapField", out isSet); | |
36 | |
37 if (value != null) | |
38 return value.ToString(); | |
39 | |
40 return base.GetFieldName(typeExtension, member, out isSet); | |
41 } | |
42 | |
43 #endregion | |
44 | |
45 #region GetFieldStorage | |
46 | |
47 public override string GetFieldStorage(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
48 { | |
49 var value = GetValue(typeExtension, member, "FieldStorage", out isSet); | |
50 | |
51 if (value != null) | |
52 return value.ToString(); | |
53 | |
54 return base.GetFieldStorage(typeExtension, member, out isSet); | |
55 } | |
56 | |
57 #endregion | |
58 | |
59 #region GetInheritanceDiscriminator | |
60 | |
61 public override bool GetInheritanceDiscriminator(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
62 { | |
63 var value = GetValue(typeExtension, member, "IsInheritanceDiscriminator", out isSet); | |
64 | |
65 if (value != null) | |
66 return TypeExtension.ToBoolean(value); | |
67 | |
68 return base.GetInheritanceDiscriminator(typeExtension, member, out isSet); | |
69 } | |
70 | |
71 #endregion | |
72 | |
73 #region GetMapIgnore | |
74 | |
75 public override bool GetMapIgnore(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
76 { | |
77 var value = GetValue(typeExtension, member, "MapIgnore", out isSet); | |
78 | |
79 if (value != null) | |
80 return TypeExtension.ToBoolean(value); | |
81 | |
82 return base.GetMapIgnore(typeExtension, member, out isSet) || GetAssociation(typeExtension, member) != null; | |
83 } | |
84 | |
85 #endregion | |
86 | |
87 #region GetMapField | |
88 | |
89 public override MapFieldAttribute GetMapField(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
90 { | |
91 var extList = typeExtension[member.Name]["MapField"]; | |
92 | |
93 if (extList != AttributeExtensionCollection.Null) | |
94 { | |
95 isSet = true; | |
96 var attr = new MapFieldAttribute(); | |
97 | |
98 var extFormat = extList.FirstOrDefault(x => x.Name == "Format"); | |
99 var extMapName = extList.FirstOrDefault(x => x.Name == "MapName"); | |
100 var extIsInheritanceDiscriminator = extList.FirstOrDefault(x => x.Name == "IsInheritanceDiscriminator"); | |
101 var extOrigName = extList.FirstOrDefault(x => x.Name == "OrigName"); | |
102 var extStorage = extList.FirstOrDefault(x => x.Name == "Storage"); | |
103 | |
104 if (extFormat != null) | |
105 attr.Format = (string)extFormat.Value; | |
106 if (extMapName != null) | |
107 attr.MapName = (string)extMapName.Value; | |
108 if (extFormat != null) | |
109 attr.IsInheritanceDiscriminator = Convert.ToBoolean(extIsInheritanceDiscriminator.Value); | |
110 if (extFormat != null) | |
111 attr.OrigName = (string)extOrigName.Value; | |
112 if (extFormat != null) | |
113 attr.Storage = (string)extStorage.Value; | |
114 return attr; | |
115 } | |
116 | |
117 return base.GetMapField(typeExtension, member, out isSet); | |
118 } | |
119 | |
120 #endregion | |
121 | |
122 #region GetDbType | |
123 | |
124 [CLSCompliant(false)] | |
125 public override DbTypeAttribute GetDbType(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
126 { | |
127 var extList = typeExtension[member.Name]["DbType"]; | |
128 | |
129 if (extList != AttributeExtensionCollection.Null) | |
130 { | |
131 isSet = true; | |
132 var attr = new DbTypeAttribute(DbType.String); | |
133 | |
134 var extDbType = extList.FirstOrDefault(x => x.Name == "DbType"); | |
135 var extSize = extList.FirstOrDefault(x => x.Name == "Size"); | |
136 | |
137 DbType dbType; | |
138 if (extDbType != null) | |
139 { | |
140 #if SILVERLIGHT || FW4 | |
141 DbType.TryParse(extDbType.Value.ToString(), out dbType); | |
142 #else | |
143 dbType = (DbType)Enum.Parse(typeof(DbType), extDbType.Value.ToString()); | |
144 #endif | |
145 attr.DbType = dbType; | |
146 } | |
147 if (extSize != null) | |
148 { | |
149 attr.Size = int.Parse(extSize.Value.ToString()); | |
150 } | |
151 return attr; | |
152 } | |
153 | |
154 return base.GetDbType(typeExtension, member, out isSet); | |
155 } | |
156 | |
157 #endregion | |
158 | |
159 #region GetPrimaryKey | |
160 | |
161 public override PrimaryKeyAttribute GetPrimaryKey(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
162 { | |
163 var extList = typeExtension[member.Name]["PrimaryKey"]; | |
164 | |
165 if (extList != AttributeExtensionCollection.Null) | |
166 { | |
167 isSet = true; | |
168 int order = -1; | |
169 var extOrder = extList.FirstOrDefault(x => x.Name == "Order"); | |
170 if (extOrder != null) | |
171 { | |
172 order = int.Parse(extOrder.Value.ToString()); | |
173 } | |
174 var attr = new PrimaryKeyAttribute(order); | |
175 return attr; | |
176 } | |
177 | |
178 return base.GetPrimaryKey(typeExtension, member, out isSet); | |
179 } | |
180 | |
181 #endregion | |
182 | |
183 | |
184 #region GetTrimmable | |
185 | |
186 public override bool GetTrimmable(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
187 { | |
188 if (member.Type == typeof(string)) | |
189 { | |
190 var value = GetValue(typeExtension, member, "Trimmable", out isSet); | |
191 | |
192 if (value != null) | |
193 return TypeExtension.ToBoolean(value); | |
194 } | |
195 | |
196 return base.GetTrimmable(typeExtension, member, out isSet); | |
197 } | |
198 | |
199 #endregion | |
200 | |
201 #region GetMapValues | |
202 | |
203 public override MapValue[] GetMapValues(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
204 { | |
205 var extList = typeExtension[member.Name]["MapValue"]; | |
206 | |
207 if (extList == AttributeExtensionCollection.Null) | |
208 return GetMapValues(typeExtension, member.Type, out isSet); | |
209 | |
210 var list = new List<MapValue>(extList.Count); | |
211 | |
212 foreach (var ext in extList) | |
213 { | |
214 var origValue = ext["OrigValue"]; | |
215 | |
216 if (origValue != null) | |
217 { | |
218 origValue = TypeExtension.ChangeType(origValue, member.Type); | |
219 list.Add(new MapValue(origValue, ext.Value)); | |
220 } | |
221 } | |
222 | |
223 isSet = true; | |
224 | |
225 return list.ToArray(); | |
226 } | |
227 | |
228 const FieldAttributes EnumField = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal; | |
229 | |
230 static List<MapValue> GetEnumMapValues(TypeExtension typeExt, Type type) | |
231 { | |
232 List<MapValue> mapValues = null; | |
233 | |
234 var fields = type.GetFields(); | |
235 | |
236 foreach (var fi in fields) | |
237 { | |
238 if ((fi.Attributes & EnumField) == EnumField) | |
239 { | |
240 var attrExt = typeExt[fi.Name]["MapValue"]; | |
241 | |
242 if (attrExt.Count == 0) | |
243 continue; | |
244 | |
245 var list = new List<object>(attrExt.Count); | |
246 var origValue = Enum.Parse(type, fi.Name, false); | |
247 | |
248 list.AddRange(from ae in attrExt where ae.Value != null select ae.Value); | |
249 | |
250 if (list.Count > 0) | |
251 { | |
252 if (mapValues == null) | |
253 mapValues = new List<MapValue>(fields.Length); | |
254 | |
255 mapValues.Add(new MapValue(origValue, list.ToArray())); | |
256 } | |
257 } | |
258 } | |
259 | |
260 return mapValues; | |
261 } | |
262 | |
263 static List<MapValue> GetTypeMapValues(TypeExtension typeExt, Type type) | |
264 { | |
265 var extList = typeExt.Attributes["MapValue"]; | |
266 | |
267 if (extList == AttributeExtensionCollection.Null) | |
268 return null; | |
269 | |
270 var attrs = new List<MapValue>(extList.Count); | |
271 | |
272 foreach (var ext in extList) | |
273 { | |
274 var origValue = ext["OrigValue"]; | |
275 | |
276 if (origValue != null) | |
277 { | |
278 origValue = TypeExtension.ChangeType(origValue, type); | |
279 attrs.Add(new MapValue(origValue, ext.Value)); | |
280 } | |
281 } | |
282 | |
283 return attrs; | |
284 } | |
285 | |
286 public override MapValue[] GetMapValues(TypeExtension typeExt, Type type, out bool isSet) | |
287 { | |
288 List<MapValue> list = null; | |
289 | |
290 if (TypeHelper.IsNullable(type)) | |
291 type = type.GetGenericArguments()[0]; | |
292 | |
293 if (type.IsEnum) | |
294 list = GetEnumMapValues(typeExt, type); | |
295 | |
296 if (list == null) | |
297 list = GetTypeMapValues(typeExt, type); | |
298 | |
299 isSet = list != null; | |
300 | |
301 return isSet? list.ToArray(): null; | |
302 } | |
303 | |
304 #endregion | |
305 | |
306 #region GetDefaultValue | |
307 | |
308 public override object GetDefaultValue(MappingSchema mappingSchema, TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
309 { | |
310 var value = typeExtension[member.Name]["DefaultValue"].Value; | |
311 | |
312 if (value != null) | |
313 { | |
314 isSet = true; | |
315 return TypeExtension.ChangeType(value, member.Type); | |
316 } | |
317 | |
318 return GetDefaultValue(mappingSchema, typeExtension, member.Type, out isSet); | |
319 } | |
320 | |
321 public override object GetDefaultValue(MappingSchema mappingSchema, TypeExtension typeExt, Type type, out bool isSet) | |
322 { | |
323 object value = null; | |
324 | |
325 if (type.IsEnum) | |
326 value = GetEnumDefaultValueFromExtension(typeExt, type); | |
327 | |
328 if (value == null) | |
329 value = typeExt.Attributes["DefaultValue"].Value; | |
330 | |
331 isSet = value != null; | |
332 | |
333 return TypeExtension.ChangeType(value, type); | |
334 } | |
335 | |
336 private static object GetEnumDefaultValueFromExtension(TypeExtension typeExt, Type type) | |
337 { | |
338 var fields = type.GetFields(); | |
339 | |
340 foreach (var fi in fields) | |
341 if ((fi.Attributes & EnumField) == EnumField) | |
342 if (typeExt[fi.Name]["DefaultValue"].Value != null) | |
343 return Enum.Parse(type, fi.Name, false); | |
344 | |
345 return null; | |
346 } | |
347 | |
348 #endregion | |
349 | |
350 #region GetNullable | |
351 | |
352 public override bool GetNullable(MappingSchema mappingSchema, TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
353 { | |
354 // Check extension <Member1 Nullable='true' /> | |
355 // | |
356 var value = GetValue(typeExtension, member, "Nullable", out isSet); | |
357 | |
358 if (isSet) | |
359 return TypeExtension.ToBoolean(value); | |
360 | |
361 // Check extension <Member1 NullValue='-1' /> | |
362 // | |
363 if (GetValue(typeExtension, member, "NullValue", out isSet) != null) | |
364 return true; | |
365 | |
366 return base.GetNullable(mappingSchema, typeExtension, member, out isSet); | |
367 } | |
368 | |
369 #endregion | |
370 | |
371 #region GetNullable | |
372 | |
373 public override bool GetLazyInstance(MappingSchema mappingSchema, TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
374 { | |
375 // Check extension <Member1 Nullable='true' /> | |
376 // | |
377 var value = GetValue(typeExtension, member, "LazyInstance", out isSet); | |
378 | |
379 if (isSet) | |
380 return TypeExtension.ToBoolean(value); | |
381 | |
382 // Check extension <Member1 NullValue='-1' /> | |
383 // | |
384 if (GetValue(typeExtension, member, "LazyInstance", out isSet) != null) | |
385 return true; | |
386 | |
387 return base.GetLazyInstance(mappingSchema, typeExtension, member, out isSet); | |
388 } | |
389 | |
390 #endregion | |
391 | |
392 #region GetNullable | |
393 | |
394 public override object GetNullValue(MappingSchema mappingSchema, TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
395 { | |
396 // Check extension <Member1 NullValue='-1' /> | |
397 // | |
398 var value = GetValue(typeExtension, member, "NullValue", out isSet); | |
399 | |
400 return isSet? TypeExtension.ChangeType(value, member.Type): null; | |
401 } | |
402 | |
403 #endregion | |
404 | |
405 #region GetDbName | |
406 | |
407 public override string GetDatabaseName(Type type, ExtensionList extensions, out bool isSet) | |
408 { | |
409 var typeExt = TypeExtension.GetTypeExtension(type, extensions); | |
410 var value = typeExt.Attributes["DatabaseName"].Value; | |
411 | |
412 if (value != null) | |
413 { | |
414 isSet = true; | |
415 return value.ToString(); | |
416 } | |
417 | |
418 return base.GetDatabaseName(type, extensions, out isSet); | |
419 } | |
420 | |
421 #endregion | |
422 | |
423 #region GetOwnerName | |
424 | |
425 public override string GetOwnerName(Type type, ExtensionList extensions, out bool isSet) | |
426 { | |
427 var typeExt = TypeExtension.GetTypeExtension(type, extensions); | |
428 var value = typeExt.Attributes["OwnerName"].Value; | |
429 | |
430 if (value != null) | |
431 { | |
432 isSet = true; | |
433 return value.ToString(); | |
434 } | |
435 | |
436 return base.GetOwnerName(type, extensions, out isSet); | |
437 } | |
438 | |
439 #endregion | |
440 | |
441 #region GetTableName | |
442 | |
443 public override string GetTableName(Type type, ExtensionList extensions, out bool isSet) | |
444 { | |
445 var typeExt = TypeExtension.GetTypeExtension(type, extensions); | |
446 var value = typeExt.Attributes["TableName"].Value; | |
447 | |
448 if (value != null) | |
449 { | |
450 isSet = true; | |
451 return value.ToString(); | |
452 } | |
453 | |
454 return base.GetTableName(type, extensions, out isSet); | |
455 } | |
456 | |
457 #endregion | |
458 | |
459 #region GetPrimaryKeyOrder | |
460 | |
461 public override int GetPrimaryKeyOrder(Type type, TypeExtension typeExt, MemberAccessor member, out bool isSet) | |
462 { | |
463 var value = typeExt[member.Name]["PrimaryKey"].Value; | |
464 | |
465 if (value != null) | |
466 { | |
467 isSet = true; | |
468 return (int)TypeExtension.ChangeType(value, typeof(int)); | |
469 } | |
470 | |
471 return base.GetPrimaryKeyOrder(type, typeExt, member, out isSet); | |
472 } | |
473 | |
474 #endregion | |
475 | |
476 #region GetNonUpdatableFlag | |
477 | |
478 public override NonUpdatableAttribute GetNonUpdatableAttribute(Type type, TypeExtension typeExt, MemberAccessor member, out bool isSet) | |
479 { | |
480 var value = typeExt[member.Name]["NonUpdatable"].Value; | |
481 | |
482 if (value != null) | |
483 { | |
484 isSet = true; | |
485 return (bool)TypeExtension.ChangeType(value, typeof(bool)) ? new NonUpdatableAttribute() : null; | |
486 } | |
487 | |
488 value = typeExt[member.Name]["Identity"].Value; | |
489 | |
490 if (value != null) | |
491 { | |
492 isSet = true; | |
493 return (bool)TypeExtension.ChangeType(value, typeof(bool)) ? new IdentityAttribute() : null; | |
494 } | |
495 | |
496 return base.GetNonUpdatableAttribute(type, typeExt, member, out isSet); | |
497 } | |
498 | |
499 #endregion | |
500 | |
501 #region GetSqlIgnore | |
502 | |
503 public override bool GetSqlIgnore(TypeExtension typeExtension, MemberAccessor member, out bool isSet) | |
504 { | |
505 var value = GetValue(typeExtension, member, "SqlIgnore", out isSet); | |
506 | |
507 if (value != null) | |
508 return TypeExtension.ToBoolean(value); | |
509 | |
510 return base.GetSqlIgnore(typeExtension, member, out isSet); | |
511 } | |
512 | |
513 #endregion | |
514 | |
515 #region GetRelations | |
516 | |
517 public override List<MapRelationBase> GetRelations(MappingSchema schema, ExtensionList typeExt, Type master, Type slave, out bool isSet) | |
518 { | |
519 var relations = new List<MapRelationBase>(); | |
520 var ext = typeExt != null ? typeExt[master] : TypeExtension.Null; | |
521 | |
522 isSet = ext != TypeExtension.Null; | |
523 | |
524 if (!isSet) | |
525 return relations; | |
526 | |
527 var ta = TypeAccessor.GetAccessor(master); | |
528 | |
529 foreach (var mex in ext.Members.Values) | |
530 { | |
531 var relationInfos = mex.Attributes[TypeExtension.NodeName.Relation]; | |
532 | |
533 if (relationInfos == AttributeExtensionCollection.Null) | |
534 continue; | |
535 | |
536 var destinationTypeName = relationInfos[0][TypeExtension.AttrName.DestinationType, string.Empty].ToString(); | |
537 var destinationType = slave; | |
538 var ma = ta[mex.Name]; | |
539 var toMany = TypeHelper.IsSameOrParent(typeof(IEnumerable), ma.Type); | |
540 | |
541 if (destinationTypeName == string.Empty) | |
542 { | |
543 if (toMany) | |
544 throw new InvalidOperationException("Destination type should be set for enumerable relations: " + ma.Type.FullName + "." + ma.Name); | |
545 | |
546 destinationType = ma.Type; | |
547 } | |
548 else | |
549 { | |
550 if (!destinationTypeName.Contains(",")) | |
551 destinationTypeName += ", " + ta.OriginalType.Assembly.FullName; | |
552 | |
553 try | |
554 { | |
555 destinationType = Type.GetType(destinationTypeName, true); | |
556 } | |
557 catch (TypeLoadException ex) | |
558 { | |
559 throw new InvalidOperationException( | |
560 "Unable to load type by name: " + destinationTypeName | |
561 + "\n may be assembly is not specefied, please see Type.GetType(string typeName) documentation", | |
562 ex); | |
563 } | |
564 } | |
565 | |
566 if (slave != null && !TypeHelper.IsSameOrParent(slave, destinationType)) | |
567 continue; | |
568 | |
569 var masterIndexFields = new List<string>(); | |
570 var slaveIndexFields = new List<string>(); | |
571 | |
572 foreach (var ae in relationInfos[0].Attributes[TypeExtension.NodeName.MasterIndex]) | |
573 masterIndexFields.Add(ae[TypeExtension.AttrName.Name].ToString()); | |
574 | |
575 foreach (var ae in relationInfos[0].Attributes[TypeExtension.NodeName.SlaveIndex]) | |
576 slaveIndexFields.Add(ae[TypeExtension.AttrName.Name].ToString()); | |
577 | |
578 | |
579 if (slaveIndexFields.Count == 0) | |
580 { | |
581 var accessor = toMany ? ta : TypeAccessor.GetAccessor(destinationType); | |
582 var tex = TypeExtension.GetTypeExtension(accessor.Type, typeExt); | |
583 | |
584 slaveIndexFields = GetPrimaryKeyFields(schema, accessor, tex); | |
585 } | |
586 | |
587 if (slaveIndexFields.Count == 0) | |
588 throw new InvalidOperationException("Slave index is not set for relation: " + ma.Type.FullName + "." + ma.Name); | |
589 | |
590 var slaveIndex = new MapIndex(slaveIndexFields.ToArray()); | |
591 var masterIndex = masterIndexFields.Count > 0 ? new MapIndex(masterIndexFields.ToArray()) : slaveIndex; | |
592 var mapRelation = new MapRelationBase(destinationType, slaveIndex, masterIndex, mex.Name); | |
593 | |
594 relations.Add(mapRelation); | |
595 | |
596 } | |
597 | |
598 isSet = relations.Count > 0; | |
599 return relations; | |
600 } | |
601 | |
602 #endregion | |
603 | |
604 #region GetAssociation | |
605 | |
606 public override Association GetAssociation(TypeExtension typeExtension, MemberAccessor member) | |
607 { | |
608 if (typeExtension == TypeExtension.Null) | |
609 return null; | |
610 | |
611 var mex = typeExtension[member.Name]; | |
612 | |
613 if (mex == MemberExtension.Null) | |
614 return null; | |
615 | |
616 var attrs = mex.Attributes[TypeExtension.NodeName.Association]; | |
617 | |
618 if (attrs == AttributeExtensionCollection.Null) | |
619 return null; | |
620 | |
621 return new Association( | |
622 member, | |
623 Association.ParseKeys(attrs[0]["ThisKey", string.Empty].ToString()), | |
624 Association.ParseKeys(attrs[0]["OtherKey", string.Empty].ToString()), | |
625 attrs[0]["Storage", string.Empty].ToString(), | |
626 TypeExtension.ToBoolean(attrs[0]["Storage", "True"], true)); | |
627 } | |
628 | |
629 #endregion | |
630 | |
631 #region GetInheritanceMapping | |
632 | |
633 public override InheritanceMappingAttribute[] GetInheritanceMapping(Type type, TypeExtension typeExtension) | |
634 { | |
635 var extList = typeExtension.Attributes["InheritanceMapping"]; | |
636 | |
637 if (extList == AttributeExtensionCollection.Null) | |
638 return Array<InheritanceMappingAttribute>.Empty; | |
639 | |
640 var attrs = new InheritanceMappingAttribute[extList.Count]; | |
641 | |
642 for (var i = 0; i < extList.Count; i++) | |
643 { | |
644 var ext = extList[i]; | |
645 | |
646 attrs[i] = new InheritanceMappingAttribute | |
647 { | |
648 Code = ext["Code"], | |
649 IsDefault = TypeExtension.ToBoolean(ext["IsDefault", "False"], false), | |
650 Type = Type.GetType(Convert.ToString(ext["Type"])) | |
651 }; | |
652 } | |
653 | |
654 return attrs; | |
655 } | |
656 | |
657 #endregion | |
658 } | |
659 } |