1 //---------------------------------------------------------------------
2 // <copyright file="MetadataPropertyCollection.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
8 //---------------------------------------------------------------------
11 using System.Collections.Generic;
12 using System.Data.Common;
13 using System.Diagnostics;
14 using System.Reflection;
15 using System.Data.Common.Utils;
17 namespace System.Data.Metadata.Edm
20 /// Metadata collection class supporting delay-loading of system item attributes and
21 /// extended attributes.
23 internal sealed class MetadataPropertyCollection : MetadataCollection<MetadataProperty>
26 /// Constructor taking item.
28 /// <param name="item">Item with which the collection is associated.</param>
29 internal MetadataPropertyCollection(MetadataItem item)
30 : base(GetSystemMetadataProperties(item))
34 private readonly static Memoizer<Type, ItemTypeInformation> s_itemTypeMemoizer =
35 new Memoizer<Type, ItemTypeInformation>(clrType => new ItemTypeInformation(clrType), null);
37 // Given an item, returns all system type attributes for the item.
38 private static IEnumerable<MetadataProperty> GetSystemMetadataProperties(MetadataItem item)
40 EntityUtil.CheckArgumentNull(item, "item");
41 Type type = item.GetType();
42 ItemTypeInformation itemTypeInformation = GetItemTypeInformation(type);
43 return itemTypeInformation.GetItemAttributes(item);
46 // Retrieves metadata for type.
47 private static ItemTypeInformation GetItemTypeInformation(Type clrType)
49 return s_itemTypeMemoizer.Evaluate(clrType);
53 /// Encapsulates information about system item attributes for a particular item type.
55 private class ItemTypeInformation
58 /// Retrieves system attribute information for the given type.
59 /// Requires: type must derive from MetadataItem
61 /// <param name="clrType">Type</param>
62 internal ItemTypeInformation(Type clrType)
64 Debug.Assert(null != clrType);
66 _itemProperties = GetItemProperties(clrType);
69 private readonly List<ItemPropertyInfo> _itemProperties;
71 // Returns system item attributes for the given item.
72 internal IEnumerable<MetadataProperty> GetItemAttributes(MetadataItem item)
74 foreach (ItemPropertyInfo propertyInfo in _itemProperties)
76 yield return propertyInfo.GetMetadataProperty(item);
80 // Gets type information for item with the given type. Uses cached information where
82 private static List<ItemPropertyInfo> GetItemProperties(Type clrType)
84 List<ItemPropertyInfo> result = new List<ItemPropertyInfo>();
85 foreach (PropertyInfo propertyInfo in clrType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
87 foreach (MetadataPropertyAttribute attribute in propertyInfo.GetCustomAttributes(
88 typeof(MetadataPropertyAttribute), false))
90 result.Add(new ItemPropertyInfo(propertyInfo, attribute));
99 /// Encapsulates information about a CLR property of an item class.
101 private class ItemPropertyInfo
104 /// Initialize information.
105 /// Requires: attribute must belong to the given property.
107 /// <param name="propertyInfo">Property referenced.</param>
108 /// <param name="attribute">Attribute for the property.</param>
109 internal ItemPropertyInfo(PropertyInfo propertyInfo, MetadataPropertyAttribute attribute)
111 Debug.Assert(null != propertyInfo);
112 Debug.Assert(null != attribute);
114 _propertyInfo = propertyInfo;
115 _attribute = attribute;
118 private readonly MetadataPropertyAttribute _attribute;
119 private readonly PropertyInfo _propertyInfo;
122 /// Given an item, returns an instance of the item attribute described by this class.
124 /// <param name="item">Item from which to retrieve attribute.</param>
125 /// <returns>Item attribute.</returns>
126 internal MetadataProperty GetMetadataProperty(MetadataItem item)
128 return new MetadataProperty(_propertyInfo.Name, _attribute.Type, _attribute.IsCollectionType,
129 new MetadataPropertyValue(_propertyInfo, item));