//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------
namespace System.Activities.Presentation.Internal.Metadata
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Activities.Presentation.Metadata;
using System.Reflection;
using System.Diagnostics;
using System.Collections;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Runtime;
//
// Helper class that knows how to look up the base implementation of a given MemberInfo,
// as well as custom attributes from the MetadataStore or the CLR. However, it does not
// actually cache those attributes. We can add this functionality in the future if needed.
// On the other hand, this class does cache the map between attribute types and our internal
// AttributeData data structures that contain AttributeUsageAttributes so we don't have to keep
// looking them up via reflection.
//
internal static class AttributeDataCache
{
// BindingFlags used for all GetInfo() types of calls
private static readonly BindingFlags _getInfoBindingFlags =
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Static;
// Note: we use Hashtables instead of Dictionaries because they are thread safe for
// read operations without the need for explicit locking.
// Hashtable of MemberInfos to their base MemberInfos, or null if there is no base MemberInfo
private static Hashtable _baseMemberMap = new Hashtable();
// Hashtable of attribute Types to their corresponding AttributeData classes
private static Hashtable _attributeDataCache = new Hashtable();
// Indicator for no MemberInfo in _baseMemberMap: Null value means the base MemberInfo wasn't
// looked up yet, _noMemberInfo value means it was looked up but it doesn't exist.
private static object _noMemberInfo = new object();
// Used for thread safety
private static object _syncObject = new object();
// This table gets populated once at initialization, so there is no need for a Hashtable here
private static Dictionary _baseMemberFinders;
// Static Ctor to populate the lookup table for helper methods that know how
// to look up the base MemberInfo of a particular MemberType (ctor, method, event, ...)
[SuppressMessage(FxCop.Category.Performance, FxCop.Rule.InitializeReferenceTypeStaticFieldsInline)]
static AttributeDataCache()
{
_baseMemberFinders = new Dictionary();
_baseMemberFinders[MemberTypes.Constructor] = new GetBaseMemberCallback(GetBaseConstructorInfo);
_baseMemberFinders[MemberTypes.Method] = new GetBaseMemberCallback(GetBaseMethodInfo);
_baseMemberFinders[MemberTypes.Property] = new GetBaseMemberCallback(GetBasePropertyInfo);
_baseMemberFinders[MemberTypes.Event] = new GetBaseMemberCallback(GetBaseEventInfo);
}
//
// Gets the base MemberInfo for the specified MemberInfo. For types,
// the method returns the base type, if any. For methods, events, and properties
// the method returns the base method, event, or property, if they exists, null
// otherwise.
//
// MemberInfo to look up in the base class
// Specified MemberInfo in the base class if it exists, null otherwise.
internal static MemberInfo GetBaseMemberInfo(MemberInfo member)
{
object baseMember = _baseMemberMap[member];
if (baseMember == _noMemberInfo)
{
return null;
}
if (baseMember == null)
{
baseMember = CalculateBaseMemberInfo(member);
// With Hashtable we only need to lock on writes
lock (_syncObject)
{
_baseMemberMap[member] = baseMember ?? _noMemberInfo;
}
}
return (MemberInfo)baseMember;
}
//
// Looks up the specified MemberInfo in the custom MetadataStore AttributeTables
// and returns any attributes associated with it as an enumeration. This method
// does not return any inherited attributes.
//
// Type to look up
// Member name to look up. If null, attributes associated
// with the type itself will be returned.
// AttributeTables to look in
// Attributes in the AttributeTables associated with the specified
// Type and member name.
internal static IEnumerable