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 }