| File: System\Reflection\TypeLoading\General\Ecma\EcmaHelpers.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.Diagnostics; using System.Reflection.Metadata; namespace System.Reflection.TypeLoading.Ecma { internal static class EcmaHelpers { /// <summary> /// Returns a RoAssemblyName corresponding to the assembly reference. /// </summary> public static RoAssemblyName ToRoAssemblyName(this AssemblyReferenceHandle h, MetadataReader reader) { AssemblyReference a = h.GetAssemblyReference(reader); string name = a.Name.GetString(reader); Version? version = a.Version.AdjustForUnspecifiedVersionComponents(); string? culture = a.Culture.GetStringOrNull(reader); byte[]? pkOrPkt = a.PublicKeyOrToken.GetBlobBytes(reader); AssemblyFlags flags = a.Flags; AssemblyNameFlags assemblyNameFlags = Helpers.ConvertAssemblyFlagsToAssemblyNameFlags(flags); if ((flags & AssemblyFlags.PublicKey) != 0) { pkOrPkt = pkOrPkt.ComputePublicKeyToken(); } return new RoAssemblyName(name, version, culture, pkOrPkt, assemblyNameFlags); } public static CoreType ToCoreType(this PrimitiveTypeCode typeCode) { switch (typeCode) { case PrimitiveTypeCode.Boolean: return CoreType.Boolean; case PrimitiveTypeCode.Byte: return CoreType.Byte; case PrimitiveTypeCode.Char: return CoreType.Char; case PrimitiveTypeCode.Double: return CoreType.Double; case PrimitiveTypeCode.Int16: return CoreType.Int16; case PrimitiveTypeCode.Int32: return CoreType.Int32; case PrimitiveTypeCode.Int64: return CoreType.Int64; case PrimitiveTypeCode.IntPtr: return CoreType.IntPtr; case PrimitiveTypeCode.Object: return CoreType.Object; case PrimitiveTypeCode.SByte: return CoreType.SByte; case PrimitiveTypeCode.Single: return CoreType.Single; case PrimitiveTypeCode.String: return CoreType.String; case PrimitiveTypeCode.TypedReference: return CoreType.TypedReference; case PrimitiveTypeCode.UInt16: return CoreType.UInt16; case PrimitiveTypeCode.UInt32: return CoreType.UInt32; case PrimitiveTypeCode.UInt64: return CoreType.UInt64; case PrimitiveTypeCode.UIntPtr: return CoreType.UIntPtr; case PrimitiveTypeCode.Void: return CoreType.Void; default: Debug.Fail("Unexpected PrimitiveTypeCode: " + typeCode); return CoreType.Void; } } public static PrimitiveTypeCode GetEnumUnderlyingPrimitiveTypeCode(this Type enumType, MetadataLoadContext loader) { Type type = enumType.GetEnumUnderlyingType(); CoreTypes coreTypes = loader.GetAllFoundCoreTypes(); // Be careful how you compare - one or more elements of "coreTypes" can be null! if (type == coreTypes[CoreType.Boolean]) return PrimitiveTypeCode.Boolean; if (type == coreTypes[CoreType.Char]) return PrimitiveTypeCode.Char; if (type == coreTypes[CoreType.Byte]) return PrimitiveTypeCode.Byte; if (type == coreTypes[CoreType.Int16]) return PrimitiveTypeCode.Int16; if (type == coreTypes[CoreType.Int32]) return PrimitiveTypeCode.Int32; if (type == coreTypes[CoreType.Int64]) return PrimitiveTypeCode.Int64; if (type == coreTypes[CoreType.IntPtr]) return PrimitiveTypeCode.IntPtr; if (type == coreTypes[CoreType.SByte]) return PrimitiveTypeCode.SByte; if (type == coreTypes[CoreType.UInt16]) return PrimitiveTypeCode.UInt16; if (type == coreTypes[CoreType.UInt32]) return PrimitiveTypeCode.UInt32; if (type == coreTypes[CoreType.UInt64]) return PrimitiveTypeCode.UInt64; if (type == coreTypes[CoreType.UIntPtr]) return PrimitiveTypeCode.UIntPtr; throw new BadImageFormatException(SR.Format(SR.UnexpectedUnderlyingEnumType, enumType, type)); } // Okay, read this closely. // // System.Reflection.AssemblyHashAlgorithm is an enum defined by System.Reflection.Metadata.dll. // // System.Configuration.Assemblies.AssemblyHashAlgorithm is an identical enum defined // by System.Runtime.dll. // // The values line up exactly so it's safe to cast from one to the other but we'll encapsulate that // observation here rather stick casts (and this painfully awkward pair of colliding type names) around. // public static System.Configuration.Assemblies.AssemblyHashAlgorithm ToConfigurationAssemblyHashAlgorithm(this System.Reflection.AssemblyHashAlgorithm srmHash) { return (System.Configuration.Assemblies.AssemblyHashAlgorithm)srmHash; } // Another case of System.Reflection and System.Reflection.Metadata defining the exact same enum. public static ExceptionHandlingClauseOptions ToExceptionHandlingClauseOptions(this ExceptionRegionKind kind) => (ExceptionHandlingClauseOptions)kind; // Yet another case of System.Reflection and System.Reflection.Metadata defining the exact same enum. public static AssemblyNameFlags ToAssemblyNameFlags(this AssemblyFlags flags) => (AssemblyNameFlags)flags; public static bool IsConstructor(this in MethodDefinition method, MetadataReader reader) { if ((method.Attributes & (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName)) != (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName)) return false; MetadataStringComparer stringComparer = reader.StringComparer; StringHandle nameHandle = method.Name; return stringComparer.Equals(nameHandle, ConstructorInfo.ConstructorName) || stringComparer.Equals(nameHandle, ConstructorInfo.TypeConstructorName); } public static unsafe ReadOnlySpan<byte> AsReadOnlySpan(this StringHandle handle, MetadataReader reader) { BlobReader br = handle.GetBlobReader(reader); return new ReadOnlySpan<byte>(br.CurrentPointer, br.Length); } public static RoMethod? ToMethodOrNull(this MethodDefinitionHandle handle, RoInstantiationProviderType declaringType, Type reflectedType) { if (handle.IsNil) return null; return handle.ToMethod(declaringType, reflectedType); } public static RoMethod ToMethod(this MethodDefinitionHandle handle, RoInstantiationProviderType declaringType, Type reflectedType) { return new RoDefinitionMethod<EcmaMethodDecoder>(declaringType, reflectedType, new EcmaMethodDecoder(handle, (EcmaModule)(declaringType.Module))); } } }