File: MetadataPropertyCollection.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (133 lines) | stat: -rw-r--r-- 5,348 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//---------------------------------------------------------------------
// <copyright file="MetadataPropertyCollection.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.Reflection;
using System.Data.Common.Utils;

namespace System.Data.Metadata.Edm
{
    /// <summary>
    /// Metadata collection class supporting delay-loading of system item attributes and
    /// extended attributes.
    /// </summary>
    internal sealed class MetadataPropertyCollection : MetadataCollection<MetadataProperty>
    {
        /// <summary>
        /// Constructor taking item.
        /// </summary>
        /// <param name="item">Item with which the collection is associated.</param>
        internal MetadataPropertyCollection(MetadataItem item)
            : base(GetSystemMetadataProperties(item))
        {
        }

        private readonly static Memoizer<Type, ItemTypeInformation> s_itemTypeMemoizer =
            new Memoizer<Type, ItemTypeInformation>(clrType => new ItemTypeInformation(clrType), null);

        // Given an item, returns all system type attributes for the item.
        private static IEnumerable<MetadataProperty> GetSystemMetadataProperties(MetadataItem item)
        {
            EntityUtil.CheckArgumentNull(item, "item");
            Type type = item.GetType();
            ItemTypeInformation itemTypeInformation = GetItemTypeInformation(type);
            return itemTypeInformation.GetItemAttributes(item);
        }

        // Retrieves metadata for type.
        private static ItemTypeInformation GetItemTypeInformation(Type clrType)
        {
            return s_itemTypeMemoizer.Evaluate(clrType);
        }

        /// <summary>
        /// Encapsulates information about system item attributes for a particular item type.
        /// </summary>
        private class ItemTypeInformation
        {
            /// <summary>
            /// Retrieves system attribute information for the given type.
            /// Requires: type must derive from MetadataItem
            /// </summary>
            /// <param name="clrType">Type</param>
            internal ItemTypeInformation(Type clrType)
            {
                Debug.Assert(null != clrType);

                _itemProperties = GetItemProperties(clrType);
            }

            private readonly List<ItemPropertyInfo> _itemProperties;

            // Returns system item attributes for the given item.
            internal IEnumerable<MetadataProperty> GetItemAttributes(MetadataItem item)
            {
                foreach (ItemPropertyInfo propertyInfo in _itemProperties)
                {
                    yield return propertyInfo.GetMetadataProperty(item);
                }
            }

            // Gets type information for item with the given type. Uses cached information where 
            // available.
            private static List<ItemPropertyInfo> GetItemProperties(Type clrType)
            {
                List<ItemPropertyInfo> result = new List<ItemPropertyInfo>();
                foreach (PropertyInfo propertyInfo in clrType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    foreach (MetadataPropertyAttribute attribute in propertyInfo.GetCustomAttributes(
                        typeof(MetadataPropertyAttribute), false))
                    {
                        result.Add(new ItemPropertyInfo(propertyInfo, attribute));
                    }
                }
                return result;
            }
        }


        /// <summary>
        /// Encapsulates information about a CLR property of an item class.
        /// </summary>
        private class ItemPropertyInfo
        {
            /// <summary>
            /// Initialize information.
            /// Requires: attribute must belong to the given property.
            /// </summary>
            /// <param name="propertyInfo">Property referenced.</param>
            /// <param name="attribute">Attribute for the property.</param>
            internal ItemPropertyInfo(PropertyInfo propertyInfo, MetadataPropertyAttribute attribute)
            {
                Debug.Assert(null != propertyInfo);
                Debug.Assert(null != attribute);

                _propertyInfo = propertyInfo;
                _attribute = attribute;
            }

            private readonly MetadataPropertyAttribute _attribute;
            private readonly PropertyInfo _propertyInfo;

            /// <summary>
            /// Given an item, returns an instance of the item attribute described by this class.
            /// </summary>
            /// <param name="item">Item from which to retrieve attribute.</param>
            /// <returns>Item attribute.</returns>
            internal MetadataProperty GetMetadataProperty(MetadataItem item)
            {
                return new MetadataProperty(_propertyInfo.Name, _attribute.Type, _attribute.IsCollectionType,
                    new MetadataPropertyValue(_propertyInfo, item));
            }
        }
    }
}