Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / Edm / MetadataPropertyCollection.cs
1 //---------------------------------------------------------------------
2 // <copyright file="MetadataPropertyCollection.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       [....]
7 // @backupOwner [....]
8 //---------------------------------------------------------------------
9
10 using System;
11 using System.Collections.Generic;
12 using System.Data.Common;
13 using System.Diagnostics;
14 using System.Reflection;
15 using System.Data.Common.Utils;
16
17 namespace System.Data.Metadata.Edm
18 {
19     /// <summary>
20     /// Metadata collection class supporting delay-loading of system item attributes and
21     /// extended attributes.
22     /// </summary>
23     internal sealed class MetadataPropertyCollection : MetadataCollection<MetadataProperty>
24     {
25         /// <summary>
26         /// Constructor taking item.
27         /// </summary>
28         /// <param name="item">Item with which the collection is associated.</param>
29         internal MetadataPropertyCollection(MetadataItem item)
30             : base(GetSystemMetadataProperties(item))
31         {
32         }
33
34         private readonly static Memoizer<Type, ItemTypeInformation> s_itemTypeMemoizer =
35             new Memoizer<Type, ItemTypeInformation>(clrType => new ItemTypeInformation(clrType), null);
36
37         // Given an item, returns all system type attributes for the item.
38         private static IEnumerable<MetadataProperty> GetSystemMetadataProperties(MetadataItem item)
39         {
40             EntityUtil.CheckArgumentNull(item, "item");
41             Type type = item.GetType();
42             ItemTypeInformation itemTypeInformation = GetItemTypeInformation(type);
43             return itemTypeInformation.GetItemAttributes(item);
44         }
45
46         // Retrieves metadata for type.
47         private static ItemTypeInformation GetItemTypeInformation(Type clrType)
48         {
49             return s_itemTypeMemoizer.Evaluate(clrType);
50         }
51
52         /// <summary>
53         /// Encapsulates information about system item attributes for a particular item type.
54         /// </summary>
55         private class ItemTypeInformation
56         {
57             /// <summary>
58             /// Retrieves system attribute information for the given type.
59             /// Requires: type must derive from MetadataItem
60             /// </summary>
61             /// <param name="clrType">Type</param>
62             internal ItemTypeInformation(Type clrType)
63             {
64                 Debug.Assert(null != clrType);
65
66                 _itemProperties = GetItemProperties(clrType);
67             }
68
69             private readonly List<ItemPropertyInfo> _itemProperties;
70
71             // Returns system item attributes for the given item.
72             internal IEnumerable<MetadataProperty> GetItemAttributes(MetadataItem item)
73             {
74                 foreach (ItemPropertyInfo propertyInfo in _itemProperties)
75                 {
76                     yield return propertyInfo.GetMetadataProperty(item);
77                 }
78             }
79
80             // Gets type information for item with the given type. Uses cached information where 
81             // available.
82             private static List<ItemPropertyInfo> GetItemProperties(Type clrType)
83             {
84                 List<ItemPropertyInfo> result = new List<ItemPropertyInfo>();
85                 foreach (PropertyInfo propertyInfo in clrType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
86                 {
87                     foreach (MetadataPropertyAttribute attribute in propertyInfo.GetCustomAttributes(
88                         typeof(MetadataPropertyAttribute), false))
89                     {
90                         result.Add(new ItemPropertyInfo(propertyInfo, attribute));
91                     }
92                 }
93                 return result;
94             }
95         }
96
97
98         /// <summary>
99         /// Encapsulates information about a CLR property of an item class.
100         /// </summary>
101         private class ItemPropertyInfo
102         {
103             /// <summary>
104             /// Initialize information.
105             /// Requires: attribute must belong to the given property.
106             /// </summary>
107             /// <param name="propertyInfo">Property referenced.</param>
108             /// <param name="attribute">Attribute for the property.</param>
109             internal ItemPropertyInfo(PropertyInfo propertyInfo, MetadataPropertyAttribute attribute)
110             {
111                 Debug.Assert(null != propertyInfo);
112                 Debug.Assert(null != attribute);
113
114                 _propertyInfo = propertyInfo;
115                 _attribute = attribute;
116             }
117
118             private readonly MetadataPropertyAttribute _attribute;
119             private readonly PropertyInfo _propertyInfo;
120
121             /// <summary>
122             /// Given an item, returns an instance of the item attribute described by this class.
123             /// </summary>
124             /// <param name="item">Item from which to retrieve attribute.</param>
125             /// <returns>Item attribute.</returns>
126             internal MetadataProperty GetMetadataProperty(MetadataItem item)
127             {
128                 return new MetadataProperty(_propertyInfo.Name, _attribute.Type, _attribute.IsCollectionType,
129                     new MetadataPropertyValue(_propertyInfo, item));
130             }
131         }
132     }
133 }