From 1ca40e79eb129b490c95c3a0bc031117b0ef81a1 Mon Sep 17 00:00:00 2001 From: Atsushi Kanamori Date: Mon, 20 Mar 2017 10:42:17 -0700 Subject: [PATCH] Move Type.cs and Module.cs to Shared Partition. Types.cs is split into the main file, Type.Helpers.cs and Type.Enum.cs. All three will be shared. - GenericTypeArguments - reconcile with CoreClr (the code is identical provided that the underlying Type provider implemented IsConstructedGenericType correctly. But we can't assume that for third party types.) - IsInterface and IsSerializable has some CoreClr specific logic for RuntimeTypes - moving this out to the unshared space for now. - IsContextFulImpl()/IsMarshalByRefImpl() - corrected implemention to match CoreClr. - IsIntegerType - no CommonRuntimeTypes in CoreClr so going back to typeof() checks - the runtime implemented types override all this enum code anyway on both runtimes. - GetRootElementType() - upgraded visibility to "internal" as a concession to CoreClr. - CoreCLR's IsVisible has a fast path - we'll keep that. - Moved IsRuntimeImplemented() out of Internal.Reflection.Core.NonPortable namespace so calls to it can be more easily shared. - Module.MethodHandle was not implemented correctly for non-runtime modules (it's supposed to return default(ModuleHandle)). This makes it behave correctly and reconciles Module.cs with the CoreCLR version. Commit migrated from https://github.com/dotnet/coreclr/commit/b94d95ec4ed7a03ae9d9d6aaa31536211b46c8cb --- .../shared/System.Private.CoreLib.Shared.projitems | 4 + .../mscorlib/shared/System/Reflection/Module.cs | 182 ++++++++ .../src/mscorlib/shared/System/Type.Enum.cs | 186 ++++++++ .../src/mscorlib/shared/System/Type.Helpers.cs | 499 +++++++++++++++++++++ src/coreclr/src/mscorlib/shared/System/Type.cs | 341 ++++++++++++++ 5 files changed, 1212 insertions(+) create mode 100644 src/coreclr/src/mscorlib/shared/System/Reflection/Module.cs create mode 100644 src/coreclr/src/mscorlib/shared/System/Type.Enum.cs create mode 100644 src/coreclr/src/mscorlib/shared/System/Type.Helpers.cs create mode 100644 src/coreclr/src/mscorlib/shared/System/Type.cs diff --git a/src/coreclr/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems b/src/coreclr/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems index 8286d37..fd12c72 100644 --- a/src/coreclr/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems +++ b/src/coreclr/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems @@ -162,6 +162,7 @@ + @@ -213,6 +214,9 @@ + + + diff --git a/src/coreclr/src/mscorlib/shared/System/Reflection/Module.cs b/src/coreclr/src/mscorlib/shared/System/Reflection/Module.cs new file mode 100644 index 0000000..56f83c4 --- /dev/null +++ b/src/coreclr/src/mscorlib/shared/System/Reflection/Module.cs @@ -0,0 +1,182 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace System.Reflection +{ + public abstract class Module : ICustomAttributeProvider, ISerializable + { + protected Module() { } + + public virtual Assembly Assembly { get { throw NotImplemented.ByDesign; } } + public virtual string FullyQualifiedName { get { throw NotImplemented.ByDesign; } } + public virtual string Name { get { throw NotImplemented.ByDesign; } } + + public virtual int MDStreamVersion { get { throw NotImplemented.ByDesign; } } + public virtual Guid ModuleVersionId { get { throw NotImplemented.ByDesign; } } + public virtual string ScopeName { get { throw NotImplemented.ByDesign; } } + public ModuleHandle ModuleHandle => GetModuleHandleImpl(); + protected virtual ModuleHandle GetModuleHandleImpl() => ModuleHandle.EmptyHandle; // Not an api but declared protected because of Reflection.Core/Corelib divide (when built by CoreRt) + public virtual void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) { throw NotImplemented.ByDesign; } + public virtual bool IsResource() { throw NotImplemented.ByDesign; } + + public virtual bool IsDefined(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; } + public virtual IEnumerable CustomAttributes => GetCustomAttributesData(); + public virtual IList GetCustomAttributesData() { throw NotImplemented.ByDesign; } + public virtual object[] GetCustomAttributes(bool inherit) { throw NotImplemented.ByDesign; } + public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; } + + public MethodInfo GetMethod(string name) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + return GetMethodImpl(name, Module.DefaultLookup, null, CallingConventions.Any, null, null); + } + + public MethodInfo GetMethod(string name, Type[] types) => GetMethod(name, Module.DefaultLookup, null, CallingConventions.Any, types, null); + public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + if (types == null) + throw new ArgumentNullException(nameof(types)); + for (int i = 0; i < types.Length; i++) + { + if (types[i] == null) + throw new ArgumentNullException(nameof(types)); + } + return GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers); + } + + protected virtual MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { throw NotImplemented.ByDesign; } + + public MethodInfo[] GetMethods() => GetMethods(Module.DefaultLookup); + public virtual MethodInfo[] GetMethods(BindingFlags bindingFlags) { throw NotImplemented.ByDesign; } + + public FieldInfo GetField(string name) => GetField(name, Module.DefaultLookup); + public virtual FieldInfo GetField(string name, BindingFlags bindingAttr) { throw NotImplemented.ByDesign; } + + public FieldInfo[] GetFields() => GetFields(Module.DefaultLookup); + public virtual FieldInfo[] GetFields(BindingFlags bindingFlags) { throw NotImplemented.ByDesign; } + + public virtual Type[] GetTypes() { throw NotImplemented.ByDesign; } + + public virtual Type GetType(string className) => GetType(className, throwOnError: false, ignoreCase: false); + public virtual Type GetType(string className, bool ignoreCase) => GetType(className, throwOnError: false, ignoreCase: ignoreCase); + public virtual Type GetType(string className, bool throwOnError, bool ignoreCase) { throw NotImplemented.ByDesign; } + + public virtual Type[] FindTypes(TypeFilter filter, object filterCriteria) + { + Type[] c = GetTypes(); + int cnt = 0; + for (int i = 0; i < c.Length; i++) + { + if (filter != null && !filter(c[i], filterCriteria)) + c[i] = null; + else + cnt++; + } + if (cnt == c.Length) + return c; + + Type[] ret = new Type[cnt]; + cnt = 0; + for (int i = 0; i < c.Length; i++) + { + if (c[i] != null) + ret[cnt++] = c[i]; + } + return ret; + } + + public virtual int MetadataToken { get { throw NotImplemented.ByDesign; } } + + public FieldInfo ResolveField(int metadataToken) => ResolveField(metadataToken, null, null); + public virtual FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { throw NotImplemented.ByDesign; } + + public MemberInfo ResolveMember(int metadataToken) => ResolveMember(metadataToken, null, null); + public virtual MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { throw NotImplemented.ByDesign; } + + public MethodBase ResolveMethod(int metadataToken) => ResolveMethod(metadataToken, null, null); + public virtual MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { throw NotImplemented.ByDesign; } + + public virtual byte[] ResolveSignature(int metadataToken) { throw NotImplemented.ByDesign; } + public virtual string ResolveString(int metadataToken) { throw NotImplemented.ByDesign; } + + public Type ResolveType(int metadataToken) => ResolveType(metadataToken, null, null); + public virtual Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { throw NotImplemented.ByDesign; } + + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw NotImplemented.ByDesign; } + + public override bool Equals(object o) => base.Equals(o); + public override int GetHashCode() => base.GetHashCode(); + + public static bool operator ==(Module left, Module right) + { + if (object.ReferenceEquals(left, right)) + return true; + + if ((object)left == null || (object)right == null) + return false; + + return left.Equals(right); + } + + public static bool operator !=(Module left, Module right) => !(left == right); + + public override string ToString() => ScopeName; + + public static readonly TypeFilter FilterTypeName = FilterTypeNameImpl; + public static readonly TypeFilter FilterTypeNameIgnoreCase = FilterTypeNameIgnoreCaseImpl; + + private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public; + + // FilterTypeName + // This method will filter the class based upon the name. It supports + // a trailing wild card. + private static bool FilterTypeNameImpl(Type cls, object filterCriteria) + { + // Check that the criteria object is a String object + if (filterCriteria == null || !(filterCriteria is string)) + throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString); + + string str = (string)filterCriteria; + + // Check to see if this is a prefix or exact match requirement + if (str.Length > 0 && str[str.Length - 1] == '*') + { + str = str.Substring(0, str.Length - 1); + return cls.Name.StartsWith(str, StringComparison.Ordinal); + } + + return cls.Name.Equals(str); + } + + // FilterFieldNameIgnoreCase + // This method filter the Type based upon name, it ignores case. + private static bool FilterTypeNameIgnoreCaseImpl(Type cls, object filterCriteria) + { + // Check that the criteria object is a String object + if (filterCriteria == null || !(filterCriteria is string)) + throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString); + + string str = (string)filterCriteria; + + // Check to see if this is a prefix or exact match requirement + if (str.Length > 0 && str[str.Length - 1] == '*') + { + str = str.Substring(0, str.Length - 1); + string name = cls.Name; + if (name.Length >= str.Length) + return (string.Compare(name, 0, str, 0, str.Length, StringComparison.OrdinalIgnoreCase) == 0); + else + return false; + } + return (string.Compare(str, cls.Name, StringComparison.OrdinalIgnoreCase) == 0); + } + } +} diff --git a/src/coreclr/src/mscorlib/shared/System/Type.Enum.cs b/src/coreclr/src/mscorlib/shared/System/Type.Enum.cs new file mode 100644 index 0000000..4d82410 --- /dev/null +++ b/src/coreclr/src/mscorlib/shared/System/Type.Enum.cs @@ -0,0 +1,186 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using System.Collections; +using System.Collections.Generic; + +namespace System +{ + // + // This file collects a set of Enum-related apis that run when the Type is subclassed by an application. + // None of it runs on normal Type objects supplied by the runtime (as those types override these methods.) + // + // Since app-subclassed Types are "untrusted classes" that may or may not implement the complete surface area correctly, + // this code should be considered brittle and not changed lightly. + // + public abstract partial class Type + { + public virtual bool IsEnumDefined(object value) + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + if (!IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); + + // Check if both of them are of the same type + Type valueType = value.GetType(); + + // If the value is an Enum then we need to extract the underlying value from it + if (valueType.IsEnum) + { + if (!valueType.IsEquivalentTo(this)) + throw new ArgumentException(SR.Format(SR.Arg_EnumAndObjectMustBeSameType, valueType.ToString(), this.ToString())); + + valueType = valueType.GetEnumUnderlyingType(); + } + + // If a string is passed in + if (valueType == typeof(string)) + { + string[] names = GetEnumNames(); + if (Array.IndexOf(names, value) >= 0) + return true; + else + return false; + } + + // If an enum or integer value is passed in + if (Type.IsIntegerType(valueType)) + { + Type underlyingType = GetEnumUnderlyingType(); + // We cannot compare the types directly because valueType is always a runtime type but underlyingType might not be. + if (underlyingType.GetTypeCodeImpl() != valueType.GetTypeCodeImpl()) + throw new ArgumentException(SR.Format(SR.Arg_EnumUnderlyingTypeAndObjectMustBeSameType, valueType.ToString(), underlyingType.ToString())); + + Array values = GetEnumRawConstantValues(); + return (BinarySearch(values, value) >= 0); + } + else + { + throw new InvalidOperationException(SR.InvalidOperation_UnknownEnumType); + } + } + + public virtual string GetEnumName(object value) + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + if (!IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); + + Type valueType = value.GetType(); + + if (!(valueType.IsEnum || Type.IsIntegerType(valueType))) + throw new ArgumentException(SR.Arg_MustBeEnumBaseTypeOrEnum, nameof(value)); + + Array values = GetEnumRawConstantValues(); + int index = BinarySearch(values, value); + + if (index >= 0) + { + string[] names = GetEnumNames(); + return names[index]; + } + + return null; + } + + public virtual string[] GetEnumNames() + { + if (!IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); + + string[] names; + Array values; + GetEnumData(out names, out values); + return names; + } + + + // Returns the enum values as an object array. + private Array GetEnumRawConstantValues() + { + string[] names; + Array values; + GetEnumData(out names, out values); + return values; + } + + // This will return enumValues and enumNames sorted by the values. + private void GetEnumData(out string[] enumNames, out Array enumValues) + { + FieldInfo[] flds = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); + + object[] values = new object[flds.Length]; + string[] names = new string[flds.Length]; + + for (int i = 0; i < flds.Length; i++) + { + names[i] = flds[i].Name; + values[i] = flds[i].GetRawConstantValue(); + } + + // Insertion Sort these values in ascending order. + // We use this O(n^2) algorithm, but it turns out that most of the time the elements are already in sorted order and + // the common case performance will be faster than quick sorting this. + IComparer comparer = Comparer.Default; + for (int i = 1; i < values.Length; i++) + { + int j = i; + string tempStr = names[i]; + object val = values[i]; + bool exchanged = false; + + // Since the elements are sorted we only need to do one comparision, we keep the check for j inside the loop. + while (comparer.Compare(values[j - 1], val) > 0) + { + names[j] = names[j - 1]; + values[j] = values[j - 1]; + j--; + exchanged = true; + if (j == 0) + break; + } + + if (exchanged) + { + names[j] = tempStr; + values[j] = val; + } + } + + enumNames = names; + enumValues = values; + } + + // Convert everything to ulong then perform a binary search. + private static int BinarySearch(Array array, object value) + { + ulong[] ulArray = new ulong[array.Length]; + for (int i = 0; i < array.Length; ++i) + ulArray[i] = Enum.ToUInt64(array.GetValue(i)); + + ulong ulValue = Enum.ToUInt64(value); + + return Array.BinarySearch(ulArray, ulValue); + } + + internal static bool IsIntegerType(Type t) + { + return (t == typeof(int) || + t == typeof(short) || + t == typeof(ushort) || + t == typeof(byte) || + t == typeof(sbyte) || + t == typeof(uint) || + t == typeof(long) || + t == typeof(ulong) || + t == typeof(char) || + t == typeof(bool)); + } + } +} diff --git a/src/coreclr/src/mscorlib/shared/System/Type.Helpers.cs b/src/coreclr/src/mscorlib/shared/System/Type.Helpers.cs new file mode 100644 index 0000000..f2f3bf6 --- /dev/null +++ b/src/coreclr/src/mscorlib/shared/System/Type.Helpers.cs @@ -0,0 +1,499 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; + +namespace System +{ + // This file collects the longer methods of Type to make the main Type class more readable. + public abstract partial class Type : MemberInfo, IReflect + { + public virtual bool ContainsGenericParameters + { + get + { + if (HasElementType) + return GetRootElementType().ContainsGenericParameters; + + if (IsGenericParameter) + return true; + + if (!IsGenericType) + return false; + + Type[] genericArguments = GetGenericArguments(); + for (int i = 0; i < genericArguments.Length; i++) + { + if (genericArguments[i].ContainsGenericParameters) + return true; + } + + return false; + } + } + + internal Type GetRootElementType() + { + Type rootElementType = this; + + while (rootElementType.HasElementType) + rootElementType = rootElementType.GetElementType(); + + return rootElementType; + } + + public bool IsVisible + { + get + { +#if CORECLR + RuntimeType rt = this as RuntimeType; + if (rt != null) + return RuntimeTypeHandle.IsVisible(rt); +#endif //CORECLR + + if (IsGenericParameter) + return true; + + if (HasElementType) + return GetElementType().IsVisible; + + Type type = this; + while (type.IsNested) + { + if (!type.IsNestedPublic) + return false; + + // this should be null for non-nested types. + type = type.DeclaringType; + } + + // Now "type" should be a top level type + if (!type.IsPublic) + return false; + + if (IsGenericType && !IsGenericTypeDefinition) + { + foreach (Type t in GetGenericArguments()) + { + if (!t.IsVisible) + return false; + } + } + + return true; + } + } + + public virtual Type[] FindInterfaces(TypeFilter filter, object filterCriteria) + { + if (filter == null) + throw new ArgumentNullException(nameof(filter)); + + Type[] c = GetInterfaces(); + int cnt = 0; + for (int i = 0; i < c.Length; i++) + { + if (!filter(c[i], filterCriteria)) + c[i] = null; + else + cnt++; + } + if (cnt == c.Length) + return c; + + Type[] ret = new Type[cnt]; + cnt = 0; + for (int i = 0; i < c.Length; i++) + { + if (c[i] != null) + ret[cnt++] = c[i]; + } + return ret; + } + + public virtual MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria) + { + // Define the work arrays + MethodInfo[] m = null; + ConstructorInfo[] c = null; + FieldInfo[] f = null; + PropertyInfo[] p = null; + EventInfo[] e = null; + Type[] t = null; + + int i = 0; + int cnt = 0; // Total Matchs + + // Check the methods + if ((memberType & MemberTypes.Method) != 0) + { + m = GetMethods(bindingAttr); + if (filter != null) + { + for (i = 0; i < m.Length; i++) + if (!filter(m[i], filterCriteria)) + m[i] = null; + else + cnt++; + } + else + { + cnt += m.Length; + } + } + + // Check the constructors + if ((memberType & MemberTypes.Constructor) != 0) + { + c = GetConstructors(bindingAttr); + if (filter != null) + { + for (i = 0; i < c.Length; i++) + if (!filter(c[i], filterCriteria)) + c[i] = null; + else + cnt++; + } + else + { + cnt += c.Length; + } + } + + // Check the fields + if ((memberType & MemberTypes.Field) != 0) + { + f = GetFields(bindingAttr); + if (filter != null) + { + for (i = 0; i < f.Length; i++) + if (!filter(f[i], filterCriteria)) + f[i] = null; + else + cnt++; + } + else + { + cnt += f.Length; + } + } + + // Check the Properties + if ((memberType & MemberTypes.Property) != 0) + { + p = GetProperties(bindingAttr); + if (filter != null) + { + for (i = 0; i < p.Length; i++) + if (!filter(p[i], filterCriteria)) + p[i] = null; + else + cnt++; + } + else + { + cnt += p.Length; + } + } + + // Check the Events + if ((memberType & MemberTypes.Event) != 0) + { + e = GetEvents(bindingAttr); + if (filter != null) + { + for (i = 0; i < e.Length; i++) + if (!filter(e[i], filterCriteria)) + e[i] = null; + else + cnt++; + } + else + { + cnt += e.Length; + } + } + + // Check the Types + if ((memberType & MemberTypes.NestedType) != 0) + { + t = GetNestedTypes(bindingAttr); + if (filter != null) + { + for (i = 0; i < t.Length; i++) + if (!filter(t[i], filterCriteria)) + t[i] = null; + else + cnt++; + } + else + { + cnt += t.Length; + } + } + + // Allocate the Member Info + MemberInfo[] ret = new MemberInfo[cnt]; + + // Copy the Methods + cnt = 0; + if (m != null) + { + for (i = 0; i < m.Length; i++) + if (m[i] != null) + ret[cnt++] = m[i]; + } + + // Copy the Constructors + if (c != null) + { + for (i = 0; i < c.Length; i++) + if (c[i] != null) + ret[cnt++] = c[i]; + } + + // Copy the Fields + if (f != null) + { + for (i = 0; i < f.Length; i++) + if (f[i] != null) + ret[cnt++] = f[i]; + } + + // Copy the Properties + if (p != null) + { + for (i = 0; i < p.Length; i++) + if (p[i] != null) + ret[cnt++] = p[i]; + } + + // Copy the Events + if (e != null) + { + for (i = 0; i < e.Length; i++) + if (e[i] != null) + ret[cnt++] = e[i]; + } + + // Copy the Types + if (t != null) + { + for (i = 0; i < t.Length; i++) + if (t[i] != null) + ret[cnt++] = t[i]; + } + + return ret; + } + + public virtual bool IsSubclassOf(Type c) + { + Type p = this; + if (p == c) + return false; + while (p != null) + { + if (p == c) + return true; + p = p.BaseType; + } + return false; + } + + public virtual bool IsAssignableFrom(Type c) + { + if (c == null) + return false; + + if (this == c) + return true; + + // For backward-compatibility, we need to special case for the types + // whose UnderlyingSystemType are runtime implemented. + Type toType = this.UnderlyingSystemType; + if (toType.IsRuntimeImplemented()) + return toType.IsAssignableFrom(c); + + // If c is a subclass of this class, then c can be cast to this type. + if (c.IsSubclassOf(this)) + return true; + + if (this.IsInterface) + { + return c.ImplementInterface(this); + } + else if (IsGenericParameter) + { + Type[] constraints = GetGenericParameterConstraints(); + for (int i = 0; i < constraints.Length; i++) + if (!constraints[i].IsAssignableFrom(c)) + return false; + + return true; + } + + return false; + } + + internal bool ImplementInterface(Type ifaceType) + { + Type t = this; + while (t != null) + { + Type[] interfaces = t.GetInterfaces(); + if (interfaces != null) + { + for (int i = 0; i < interfaces.Length; i++) + { + // Interfaces don't derive from other interfaces, they implement them. + // So instead of IsSubclassOf, we should use ImplementInterface instead. + if (interfaces[i] == ifaceType || + (interfaces[i] != null && interfaces[i].ImplementInterface(ifaceType))) + return true; + } + } + + t = t.BaseType; + } + + return false; + } + + // FilterAttribute + // This method will search for a member based upon the attribute passed in. + // filterCriteria -- an Int32 representing the attribute + private static bool FilterAttributeImpl(MemberInfo m, object filterCriteria) + { + // Check that the criteria object is an Integer object + if (filterCriteria == null) + throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritInt); + + switch (m.MemberType) + { + case MemberTypes.Constructor: + case MemberTypes.Method: + { + MethodAttributes criteria = 0; + try + { + int i = (int)filterCriteria; + criteria = (MethodAttributes)i; + } + catch + { + throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritInt); + } + + + MethodAttributes attr; + if (m.MemberType == MemberTypes.Method) + attr = ((MethodInfo)m).Attributes; + else + attr = ((ConstructorInfo)m).Attributes; + + if (((criteria & MethodAttributes.MemberAccessMask) != 0) && (attr & MethodAttributes.MemberAccessMask) != (criteria & MethodAttributes.MemberAccessMask)) + return false; + if (((criteria & MethodAttributes.Static) != 0) && (attr & MethodAttributes.Static) == 0) + return false; + if (((criteria & MethodAttributes.Final) != 0) && (attr & MethodAttributes.Final) == 0) + return false; + if (((criteria & MethodAttributes.Virtual) != 0) && (attr & MethodAttributes.Virtual) == 0) + return false; + if (((criteria & MethodAttributes.Abstract) != 0) && (attr & MethodAttributes.Abstract) == 0) + return false; + if (((criteria & MethodAttributes.SpecialName) != 0) && (attr & MethodAttributes.SpecialName) == 0) + return false; + return true; + } + case MemberTypes.Field: + { + FieldAttributes criteria = 0; + try + { + int i = (int)filterCriteria; + criteria = (FieldAttributes)i; + } + catch + { + throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritInt); + } + + FieldAttributes attr = ((FieldInfo)m).Attributes; + if (((criteria & FieldAttributes.FieldAccessMask) != 0) && (attr & FieldAttributes.FieldAccessMask) != (criteria & FieldAttributes.FieldAccessMask)) + return false; + if (((criteria & FieldAttributes.Static) != 0) && (attr & FieldAttributes.Static) == 0) + return false; + if (((criteria & FieldAttributes.InitOnly) != 0) && (attr & FieldAttributes.InitOnly) == 0) + return false; + if (((criteria & FieldAttributes.Literal) != 0) && (attr & FieldAttributes.Literal) == 0) + return false; + if (((criteria & FieldAttributes.NotSerialized) != 0) && (attr & FieldAttributes.NotSerialized) == 0) + return false; + if (((criteria & FieldAttributes.PinvokeImpl) != 0) && (attr & FieldAttributes.PinvokeImpl) == 0) + return false; + return true; + } + } + + return false; + } + + // FilterName + // This method will filter based upon the name. A partial wildcard + // at the end of the string is supported. + // filterCriteria -- This is the string name + private static bool FilterNameImpl(MemberInfo m, object filterCriteria) + { + // Check that the criteria object is a String object + if (filterCriteria == null || !(filterCriteria is string)) + throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString); + + // At the moment this fails if its done on a single line.... + string str = ((string)filterCriteria); + str = str.Trim(); + + string name = m.Name; + // Get the nested class name only, as opposed to the mangled one + if (m.MemberType == MemberTypes.NestedType) + name = name.Substring(name.LastIndexOf('+') + 1); + // Check to see if this is a prefix or exact match requirement + if (str.Length > 0 && str[str.Length - 1] == '*') + { + str = str.Substring(0, str.Length - 1); + return (name.StartsWith(str, StringComparison.Ordinal)); + } + + return (name.Equals(str)); + } + + // FilterIgnoreCase + // This delegate will do a name search but does it with the + // ignore case specified. + private static bool FilterNameIgnoreCaseImpl(MemberInfo m, object filterCriteria) + { + // Check that the criteria object is a String object + if (filterCriteria == null || !(filterCriteria is string)) + throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString); + + string str = (string)filterCriteria; + str = str.Trim(); + + string name = m.Name; + // Get the nested class name only, as opposed to the mangled one + if (m.MemberType == MemberTypes.NestedType) + name = name.Substring(name.LastIndexOf('+') + 1); + // Check to see if this is a prefix or exact match requirement + if (str.Length > 0 && str[str.Length - 1] == '*') + { + str = str.Substring(0, str.Length - 1); + return (string.Compare(name, 0, str, 0, str.Length, StringComparison.OrdinalIgnoreCase) == 0); + } + + return (string.Compare(str, name, StringComparison.OrdinalIgnoreCase) == 0); + } + } +} + diff --git a/src/coreclr/src/mscorlib/shared/System/Type.cs b/src/coreclr/src/mscorlib/shared/System/Type.cs new file mode 100644 index 0000000..09a72aa --- /dev/null +++ b/src/coreclr/src/mscorlib/shared/System/Type.cs @@ -0,0 +1,341 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace System +{ + public abstract partial class Type : MemberInfo, IReflect + { + protected Type() { } + + public override MemberTypes MemberType => MemberTypes.TypeInfo; + + public new Type GetType() => base.GetType(); + + public abstract string Namespace { get; } + public abstract string AssemblyQualifiedName { get; } + public abstract string FullName { get; } + + public abstract Assembly Assembly { get; } + public abstract new Module Module { get; } + + public bool IsNested => DeclaringType != null; + public override Type DeclaringType => null; + public virtual MethodBase DeclaringMethod => null; + + public override Type ReflectedType => null; + public abstract Type UnderlyingSystemType { get; } + + public bool IsArray => IsArrayImpl(); + protected abstract bool IsArrayImpl(); + public bool IsByRef => IsByRefImpl(); + protected abstract bool IsByRefImpl(); + public bool IsPointer => IsPointerImpl(); + protected abstract bool IsPointerImpl(); + public virtual bool IsConstructedGenericType { get { throw NotImplemented.ByDesign; } } + public virtual bool IsGenericParameter => false; + public virtual bool IsGenericType => false; + public virtual bool IsGenericTypeDefinition => false; + + public virtual bool IsSZArray { get { throw NotImplemented.ByDesign; } } + + public bool HasElementType => HasElementTypeImpl(); + protected abstract bool HasElementTypeImpl(); + public abstract Type GetElementType(); + + public virtual int GetArrayRank() { throw new NotSupportedException(SR.NotSupported_SubclassOverride); } + + public virtual Type GetGenericTypeDefinition() { throw new NotSupportedException(SR.NotSupported_SubclassOverride); } + public virtual Type[] GenericTypeArguments => (IsGenericType && !IsGenericTypeDefinition) ? GetGenericArguments() : Array.Empty(); + public virtual Type[] GetGenericArguments() { throw new NotSupportedException(SR.NotSupported_SubclassOverride); } + + public virtual int GenericParameterPosition { get { throw new InvalidOperationException(SR.Arg_NotGenericParameter); } } + public virtual GenericParameterAttributes GenericParameterAttributes { get { throw new NotSupportedException(); } } + public virtual Type[] GetGenericParameterConstraints() + { + if (!IsGenericParameter) + throw new InvalidOperationException(SR.Arg_NotGenericParameter); + throw new InvalidOperationException(); + } + + public TypeAttributes Attributes => GetAttributeFlagsImpl(); + protected abstract TypeAttributes GetAttributeFlagsImpl(); + + public bool IsAbstract => (GetAttributeFlagsImpl() & TypeAttributes.Abstract) != 0; + public bool IsImport => (GetAttributeFlagsImpl() & TypeAttributes.Import) != 0; + public bool IsSealed => (GetAttributeFlagsImpl() & TypeAttributes.Sealed) != 0; + public bool IsSpecialName => (GetAttributeFlagsImpl() & TypeAttributes.SpecialName) != 0; + + public bool IsClass => (GetAttributeFlagsImpl() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class && !IsValueType; + + public bool IsNestedAssembly => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly; + public bool IsNestedFamANDAssem => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem; + public bool IsNestedFamily => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily; + public bool IsNestedFamORAssem => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem; + public bool IsNestedPrivate => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate; + public bool IsNestedPublic => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic; + public bool IsNotPublic => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic; + public bool IsPublic => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.Public; + + public bool IsAutoLayout => (GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout; + public bool IsExplicitLayout => (GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout; + public bool IsLayoutSequential => (GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout; + + public bool IsAnsiClass => (GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.AnsiClass; + public bool IsAutoClass => (GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass; + public bool IsUnicodeClass => (GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass; + + public bool IsCOMObject => IsCOMObjectImpl(); + protected abstract bool IsCOMObjectImpl(); + public bool IsContextful => IsContextfulImpl(); + protected virtual bool IsContextfulImpl() => false; + + public virtual bool IsEnum => IsSubclassOf(typeof(Enum)); + public bool IsMarshalByRef => IsMarshalByRefImpl(); + protected virtual bool IsMarshalByRefImpl() => false; + public bool IsPrimitive => IsPrimitiveImpl(); + protected abstract bool IsPrimitiveImpl(); + public bool IsValueType => IsValueTypeImpl(); + protected virtual bool IsValueTypeImpl() => IsSubclassOf(typeof(ValueType)); + + public virtual bool IsSecurityCritical { get { throw NotImplemented.ByDesign; } } + public virtual bool IsSecuritySafeCritical { get { throw NotImplemented.ByDesign; } } + public virtual bool IsSecurityTransparent { get { throw NotImplemented.ByDesign; } } + + public virtual StructLayoutAttribute StructLayoutAttribute { get { throw new NotSupportedException(); } } + public ConstructorInfo TypeInitializer => GetConstructorImpl(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, Type.EmptyTypes, null); + + public ConstructorInfo GetConstructor(Type[] types) => GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, types, null); + public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) => GetConstructor(bindingAttr, binder, CallingConventions.Any, types, modifiers); + public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + { + if (types == null) + throw new ArgumentNullException(nameof(types)); + for (int i = 0; i < types.Length; i++) + { + if (types[i] == null) + throw new ArgumentNullException(nameof(types)); + } + return GetConstructorImpl(bindingAttr, binder, callConvention, types, modifiers); + } + protected abstract ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers); + + public ConstructorInfo[] GetConstructors() => GetConstructors(BindingFlags.Public | BindingFlags.Instance); + public abstract ConstructorInfo[] GetConstructors(BindingFlags bindingAttr); + + public EventInfo GetEvent(string name) => GetEvent(name, Type.DefaultLookup); + public abstract EventInfo GetEvent(string name, BindingFlags bindingAttr); + + public virtual EventInfo[] GetEvents() => GetEvents(Type.DefaultLookup); + public abstract EventInfo[] GetEvents(BindingFlags bindingAttr); + + public FieldInfo GetField(string name) => GetField(name, Type.DefaultLookup); + public abstract FieldInfo GetField(string name, BindingFlags bindingAttr); + + public FieldInfo[] GetFields() => GetFields(Type.DefaultLookup); + public abstract FieldInfo[] GetFields(BindingFlags bindingAttr); + + public MemberInfo[] GetMember(string name) => GetMember(name, Type.DefaultLookup); + public virtual MemberInfo[] GetMember(string name, BindingFlags bindingAttr) => GetMember(name, MemberTypes.All, bindingAttr); + public virtual MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); } + + public MemberInfo[] GetMembers() => GetMembers(Type.DefaultLookup); + public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr); + + public MethodInfo GetMethod(string name) => GetMethod(name, Type.DefaultLookup); + public MethodInfo GetMethod(string name, BindingFlags bindingAttr) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + return GetMethodImpl(name, bindingAttr, null, CallingConventions.Any, null, null); + } + + public MethodInfo GetMethod(string name, Type[] types) => GetMethod(name, types, null); + public MethodInfo GetMethod(string name, Type[] types, ParameterModifier[] modifiers) => GetMethod(name, Type.DefaultLookup, null, types, modifiers); + public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) => GetMethod(name, bindingAttr, binder, CallingConventions.Any, types, modifiers); + public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + if (types == null) + throw new ArgumentNullException(nameof(types)); + for (int i = 0; i < types.Length; i++) + { + if (types[i] == null) + throw new ArgumentNullException(nameof(types)); + } + return GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers); + } + + protected abstract MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers); + + public MethodInfo[] GetMethods() => GetMethods(Type.DefaultLookup); + public abstract MethodInfo[] GetMethods(BindingFlags bindingAttr); + + public Type GetNestedType(string name) => GetNestedType(name, Type.DefaultLookup); + public abstract Type GetNestedType(string name, BindingFlags bindingAttr); + + public Type[] GetNestedTypes() => GetNestedTypes(Type.DefaultLookup); + public abstract Type[] GetNestedTypes(BindingFlags bindingAttr); + + public PropertyInfo GetProperty(string name) => GetProperty(name, Type.DefaultLookup); + public PropertyInfo GetProperty(string name, BindingFlags bindingAttr) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + return GetPropertyImpl(name, bindingAttr, null, null, null, null); + } + + public PropertyInfo GetProperty(string name, Type returnType) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + if (returnType == null) + throw new ArgumentNullException(nameof(returnType)); + return GetPropertyImpl(name, Type.DefaultLookup, null, returnType, null, null); + } + + public PropertyInfo GetProperty(string name, Type[] types) => GetProperty(name, null, types); + public PropertyInfo GetProperty(string name, Type returnType, Type[] types) => GetProperty(name, returnType, types, null); + public PropertyInfo GetProperty(string name, Type returnType, Type[] types, ParameterModifier[] modifiers) => GetProperty(name, Type.DefaultLookup, null, returnType, types, modifiers); + public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + if (types == null) + throw new ArgumentNullException(nameof(types)); + return GetPropertyImpl(name, bindingAttr, binder, returnType, types, modifiers); + } + + protected abstract PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers); + + public PropertyInfo[] GetProperties() => GetProperties(Type.DefaultLookup); + public abstract PropertyInfo[] GetProperties(BindingFlags bindingAttr); + + public virtual MemberInfo[] GetDefaultMembers() { throw NotImplemented.ByDesign; } + + public virtual RuntimeTypeHandle TypeHandle { get { throw new NotSupportedException(); } } + public static RuntimeTypeHandle GetTypeHandle(object o) + { + if (o == null) + throw new ArgumentNullException(null, SR.Arg_InvalidHandle); + Type type = o.GetType(); + return type.TypeHandle; + } + + public static Type[] GetTypeArray(object[] args) + { + if (args == null) + throw new ArgumentNullException(nameof(args)); + + Type[] cls = new Type[args.Length]; + for (int i = 0; i < cls.Length; i++) + { + if (args[i] == null) + throw new ArgumentNullException(); + cls[i] = args[i].GetType(); + } + return cls; + } + + public static TypeCode GetTypeCode(Type type) + { + if (type == null) + return TypeCode.Empty; + return type.GetTypeCodeImpl(); + } + protected virtual TypeCode GetTypeCodeImpl() + { + if (this != UnderlyingSystemType && UnderlyingSystemType != null) + return Type.GetTypeCode(UnderlyingSystemType); + + return TypeCode.Object; + } + + public abstract Guid GUID { get; } + + public static Type GetTypeFromCLSID(Guid clsid) => GetTypeFromCLSID(clsid, null, throwOnError: false); + public static Type GetTypeFromCLSID(Guid clsid, bool throwOnError) => GetTypeFromCLSID(clsid, null, throwOnError: throwOnError); + public static Type GetTypeFromCLSID(Guid clsid, string server) => GetTypeFromCLSID(clsid, server, throwOnError: false); + + public static Type GetTypeFromProgID(string progID) => GetTypeFromProgID(progID, null, throwOnError: false); + public static Type GetTypeFromProgID(string progID, bool throwOnError) => GetTypeFromProgID(progID, null, throwOnError: throwOnError); + public static Type GetTypeFromProgID(string progID, string server) => GetTypeFromProgID(progID, server, throwOnError: false); + + public abstract Type BaseType { get; } + + [DebuggerHidden] + [DebuggerStepThrough] + public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args) => InvokeMember(name, invokeAttr, binder, target, args, null, null, null); + + [DebuggerHidden] + [DebuggerStepThrough] + public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, CultureInfo culture) => InvokeMember(name, invokeAttr, binder, target, args, null, culture, null); + public abstract object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters); + + public Type GetInterface(string name) => GetInterface(name, ignoreCase: false); + public abstract Type GetInterface(string name, bool ignoreCase); + public abstract Type[] GetInterfaces(); + + public virtual InterfaceMapping GetInterfaceMap(Type interfaceType) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); } + + public virtual bool IsInstanceOfType(object o) => o == null ? false : IsAssignableFrom(o.GetType()); + public virtual bool IsEquivalentTo(Type other) => this == other; + + public virtual Type GetEnumUnderlyingType() + { + if (!IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); + + FieldInfo[] fields = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + if (fields == null || fields.Length != 1) + throw new ArgumentException(SR.Argument_InvalidEnum, "enumType"); + + return fields[0].FieldType; + } + public virtual Array GetEnumValues() + { + if (!IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); + + // We don't support GetEnumValues in the default implementation because we cannot create an array of + // a non-runtime type. If there is strong need we can consider returning an object or int64 array. + throw NotImplemented.ByDesign; + } + + public virtual Type MakeArrayType() { throw new NotSupportedException(); } + public virtual Type MakeArrayType(int rank) { throw new NotSupportedException(); } + public virtual Type MakeByRefType() { throw new NotSupportedException(); } + public virtual Type MakeGenericType(params Type[] typeArguments) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); } + public virtual Type MakePointerType() { throw new NotSupportedException(); } + + public override string ToString() => "Type: " + Name; // Why do we add the "Type: " prefix? + + public override bool Equals(object o) => o == null ? false : Equals(o as Type); + public override int GetHashCode() + { + Type systemType = UnderlyingSystemType; + if (!object.ReferenceEquals(systemType, this)) + return systemType.GetHashCode(); + return base.GetHashCode(); + } + public virtual bool Equals(Type o) => o == null ? false : object.ReferenceEquals(this.UnderlyingSystemType, o.UnderlyingSystemType); + + public static Type ReflectionOnlyGetType(string typeName, bool throwIfNotFound, bool ignoreCase) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); } + + public static readonly char Delimiter = '.'; + public static readonly Type[] EmptyTypes = Array.Empty(); + public static readonly object Missing = System.Reflection.Missing.Value; + + public static readonly MemberFilter FilterAttribute = FilterAttributeImpl; + public static readonly MemberFilter FilterName = FilterNameImpl; + public static readonly MemberFilter FilterNameIgnoreCase = FilterNameIgnoreCaseImpl; + + private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public; + } +} -- 2.7.4