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));
}
}
}
}
|