3 // Copyright(c) Microsoft Corporation. All rights reserved.
6 // <OWNER>Microsoft</OWNER>
9 namespace System.Reflection
12 using System.Collections.Generic;
13 using System.Diagnostics.Contracts;
15 internal static class Associates
18 internal enum Attributes
20 ComposedOfAllVirtualMethods = 0x1,
21 ComposedOfAllPrivateMethods = 0x2,
22 ComposedOfNoPublicMembers = 0x4,
23 ComposedOfNoStaticMembers = 0x8,
26 internal static bool IncludeAccessor(MethodInfo associate, bool nonPublic)
28 if ((object)associate == null)
34 if (associate.IsPublic)
40 [System.Security.SecurityCritical] // auto-generated
41 private static unsafe RuntimeMethodInfo AssignAssociates(
43 RuntimeType declaredType,
44 RuntimeType reflectedType)
46 if (MetadataToken.IsNullToken(tkMethod))
49 Contract.Assert(declaredType != null);
50 Contract.Assert(reflectedType != null);
52 bool isInherited = declaredType != reflectedType;
54 IntPtr[] genericArgumentHandles = null;
55 int genericArgumentCount = 0;
56 RuntimeType [] genericArguments = declaredType.GetTypeHandleInternal().GetInstantiationInternal();
57 if (genericArguments != null)
59 genericArgumentCount = genericArguments.Length;
60 genericArgumentHandles = new IntPtr[genericArguments.Length];
61 for (int i = 0; i < genericArguments.Length; i++)
63 genericArgumentHandles[i] = genericArguments[i].GetTypeHandleInternal().Value;
67 RuntimeMethodHandleInternal associateMethodHandle = ModuleHandle.ResolveMethodHandleInternalCore(RuntimeTypeHandle.GetModule(declaredType), tkMethod, genericArgumentHandles, genericArgumentCount, null, 0);
68 Contract.Assert(!associateMethodHandle.IsNullHandle(), "Failed to resolve associateRecord methodDef token");
72 MethodAttributes methAttr = RuntimeMethodHandle.GetAttributes(associateMethodHandle);
74 // ECMA MethodSemantics: "All methods for a given Property or Event shall have the same accessibility
75 //(ie the MemberAccessMask subfield of their Flags row) and cannot be CompilerControlled [CLS]"
76 // Consequently, a property may be composed of public and private methods. If the declared type !=
77 // the reflected type, the private methods should not be exposed. Note that this implies that the
78 // identity of a property includes it's reflected type.
80 // NetCF actually includes private methods from parent classes in Reflection results
81 // We will mimic that in Mango Compat mode.
82 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
84 if ((methAttr & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
88 // Note this is the first time the property was encountered walking from the most derived class
89 // towards the base class. It would seem to follow that any associated methods would not
90 // be overriden -- but this is not necessarily true. A more derived class may have overriden a
91 // virtual method associated with a property in a base class without associating the override with
92 // the same or any property in the derived class.
93 if ((methAttr & MethodAttributes.Virtual) != 0)
95 bool declaringTypeIsClass =
96 (RuntimeTypeHandle.GetAttributes(declaredType) & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class;
98 // It makes no sense to search for a virtual override of a method declared on an interface.
99 if (declaringTypeIsClass)
101 int slot = RuntimeMethodHandle.GetSlot(associateMethodHandle);
103 // Find the override visible from the reflected type
104 associateMethodHandle = RuntimeTypeHandle.GetMethodAt(reflectedType, slot);
109 RuntimeMethodInfo associateMethod =
110 RuntimeType.GetMethodBase(reflectedType, associateMethodHandle) as RuntimeMethodInfo;
112 // suppose a property was mapped to a method not in the derivation hierarchy of the reflectedTypeHandle
113 if (associateMethod == null)
114 associateMethod = reflectedType.Module.ResolveMethod(tkMethod, null, null) as RuntimeMethodInfo;
116 return associateMethod;
119 [System.Security.SecurityCritical] // auto-generated
120 internal static unsafe void AssignAssociates(
121 MetadataImport scope,
123 RuntimeType declaringType,
124 RuntimeType reflectedType,
125 out RuntimeMethodInfo addOn,
126 out RuntimeMethodInfo removeOn,
127 out RuntimeMethodInfo fireOn,
128 out RuntimeMethodInfo getter,
129 out RuntimeMethodInfo setter,
130 out MethodInfo[] other,
131 out bool composedOfAllPrivateMethods,
132 out BindingFlags bindingFlags)
134 addOn = removeOn = fireOn = getter = setter = null;
136 Attributes attributes =
137 Attributes.ComposedOfAllPrivateMethods |
138 Attributes.ComposedOfAllVirtualMethods |
139 Attributes.ComposedOfNoPublicMembers |
140 Attributes.ComposedOfNoStaticMembers;
142 while(RuntimeTypeHandle.IsGenericVariable(reflectedType))
143 reflectedType = (RuntimeType)reflectedType.BaseType;
145 bool isInherited = declaringType != reflectedType;
147 List<MethodInfo> otherList = null;
149 MetadataEnumResult associatesData;
150 scope.Enum(MetadataTokenType.MethodDef, mdPropEvent, out associatesData);
152 int cAssociates = associatesData.Length / 2;
154 for (int i = 0; i < cAssociates; i++)
156 int methodDefToken = associatesData[i * 2];
157 MethodSemanticsAttributes semantics = (MethodSemanticsAttributes)associatesData[i * 2 + 1];
159 #region Assign each associate
160 RuntimeMethodInfo associateMethod =
161 AssignAssociates(methodDefToken, declaringType, reflectedType);
163 if (associateMethod == null)
166 MethodAttributes methAttr = associateMethod.Attributes;
167 bool isPrivate =(methAttr & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
168 bool isVirtual =(methAttr & MethodAttributes.Virtual) != 0;
170 MethodAttributes visibility = methAttr & MethodAttributes.MemberAccessMask;
171 bool isPublic = visibility == MethodAttributes.Public;
172 bool isStatic =(methAttr & MethodAttributes.Static) != 0;
176 attributes &= ~Attributes.ComposedOfNoPublicMembers;
177 attributes &= ~Attributes.ComposedOfAllPrivateMethods;
181 attributes &= ~Attributes.ComposedOfAllPrivateMethods;
185 attributes &= ~Attributes.ComposedOfNoStaticMembers;
188 attributes &= ~Attributes.ComposedOfAllVirtualMethods;
191 if (semantics == MethodSemanticsAttributes.Setter)
192 setter = associateMethod;
193 else if (semantics == MethodSemanticsAttributes.Getter)
194 getter = associateMethod;
195 else if (semantics == MethodSemanticsAttributes.Fire)
196 fireOn = associateMethod;
197 else if (semantics == MethodSemanticsAttributes.AddOn)
198 addOn = associateMethod;
199 else if (semantics == MethodSemanticsAttributes.RemoveOn)
200 removeOn = associateMethod;
203 if (otherList == null)
204 otherList = new List<MethodInfo>(cAssociates);
205 otherList.Add(associateMethod);
209 bool isPseudoPublic = (attributes & Attributes.ComposedOfNoPublicMembers) == 0;
210 bool isPseudoStatic = (attributes & Attributes.ComposedOfNoStaticMembers) == 0;
211 bindingFlags = RuntimeType.FilterPreCalculate(isPseudoPublic, isInherited, isPseudoStatic);
213 composedOfAllPrivateMethods =(attributes & Attributes.ComposedOfAllPrivateMethods) != 0;
215 other = (otherList != null) ? otherList.ToArray() : null;