| File: System\Reflection\TypeLoading\Types\RoArrayType.cs | Web Access |
| Project: src\runtime\src\libraries\System.Reflection.MetadataLoadContext\src\System.Reflection.MetadataLoadContext.csproj (System.Reflection.MetadataLoadContext) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; namespace System.Reflection.TypeLoading { /// <summary> /// All RoTypes that return true for IsArray. This includes both SZArrays and multi-dim arrays. /// </summary> internal sealed partial class RoArrayType : RoHasElementType { private readonly bool _multiDim; private readonly int _rank; internal RoArrayType(RoType elementType, bool multiDim, int rank) : base(elementType) { Debug.Assert(elementType != null); Debug.Assert(multiDim || rank == 1); _multiDim = multiDim; _rank = rank; } protected sealed override bool IsArrayImpl() => true; public sealed override bool IsSZArray => !_multiDim; public sealed override bool IsVariableBoundArray => _multiDim; protected sealed override bool IsByRefImpl() => false; protected sealed override bool IsPointerImpl() => false; protected sealed override string Suffix => Helpers.ComputeArraySuffix(_rank, _multiDim); public sealed override int GetArrayRank() => _rank; internal sealed override RoType? ComputeBaseTypeWithoutDesktopQuirk() => Loader.GetCoreType(CoreType.Array); internal sealed override IEnumerable<RoType> ComputeDirectlyImplementedInterfaces() { if (_multiDim) yield break; RoType[] typeArguments = { GetRoElementType() }; foreach (CoreType coreType in s_typesImplementedByArray) { RoType? ifc = Loader.TryGetCoreType(coreType); if (ifc != null) { // All of our types are from a fixed list so we know they're supposed be generic interfaces taking one type parameter. // But since we're loading them from a core assembly that the user supplied us, we should verify and skip if // this is not the case. if (ifc is RoDefinitionType roDefinitionType && roDefinitionType.GetGenericParameterCount() == 1) { yield return roDefinitionType.GetUniqueConstructedGenericType(typeArguments); } } } } private static readonly CoreType[] s_typesImplementedByArray = { CoreType.IEnumerableT, CoreType.ICollectionT, CoreType.IListT, CoreType.IReadOnlyListT, }; #pragma warning disable SYSLIB0050 // TypeAttributes.Serialized flag is obsolete protected sealed override TypeAttributes ComputeAttributeFlags() => TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable; #pragma warning restore SYSLIB0050 internal sealed override IEnumerable<ConstructorInfo> GetConstructorsCore(NameFilter? filter) { if (filter == null || filter.Matches(ConstructorInfo.ConstructorName)) { int rank = _rank; bool multiDim = _multiDim; RoType systemInt32 = Loader.GetCoreType(CoreType.Int32); int uniquifier = 0; // // Expose a constructor that takes n Int32's (one for each dimension) and constructs a zero lower-bounded array. For example, // // String[,] // // exposes // // .ctor(int32, int32) // { RoType[] parameterTypes = new RoType[rank]; for (int i = 0; i < rank; i++) { parameterTypes[i] = systemInt32; } yield return new RoSyntheticConstructor(this, uniquifier++, parameterTypes); } if (!multiDim) { // // Jagged arrays also expose constructors that take multiple indices and construct a jagged matrix. For example, // // String[][][][] // // also exposes: // // .ctor(int32, int32) // .ctor(int32, int32, int32) // .ctor(int32, int32, int32, int32) // int parameterCount = 2; RoType elementType = GetRoElementType(); while (elementType.IsSZArray) { RoType[] parameterTypes = new RoType[parameterCount]; for (int i = 0; i < parameterCount; i++) { parameterTypes[i] = systemInt32; } yield return new RoSyntheticConstructor(this, uniquifier++, parameterTypes); parameterCount++; elementType = elementType.GetRoElementType()!; } } if (multiDim) { // // Expose a constructor that takes n*2 Int32's (two for each dimension) and constructs a arbitrarily lower-bounded array. For example, // // String[,] // // exposes // // .ctor(int32, int32, int32, int32) // RoType[] parameterTypes = new RoType[rank * 2]; for (int i = 0; i < rank * 2; i++) { parameterTypes[i] = systemInt32; } yield return new RoSyntheticConstructor(this, uniquifier++, parameterTypes); } } } internal sealed override IEnumerable<MethodInfo> GetMethodsCore(NameFilter? filter, Type reflectedType) { int rank = _rank; RoType systemInt32 = Loader.GetCoreType(CoreType.Int32); RoType elementType = GetRoElementType(); RoType systemVoid = Loader.GetCoreType(CoreType.Void); if (filter == null || filter.Matches("Get")) { RoType[] getParameters = new RoType[rank]; for (int i = 0; i < rank; i++) { getParameters[i] = systemInt32; } yield return new RoSyntheticMethod(this, 0, "Get", elementType, getParameters); } if (filter == null || filter.Matches("Set")) { RoType[] setParameters = new RoType[rank + 1]; for (int i = 0; i < rank; i++) { setParameters[i] = systemInt32; } setParameters[rank] = elementType; yield return new RoSyntheticMethod(this, 1, "Set", systemVoid, setParameters); } if (filter == null || filter.Matches("Address")) { RoType[] addressParameters = new RoType[rank]; for (int i = 0; i < rank; i++) { addressParameters[i] = systemInt32; } yield return new RoSyntheticMethod(this, 2, "Address", elementType.GetUniqueByRefType(), addressParameters); } } } }