| File: System\Reflection\TypeLoading\Modules\RoModule.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.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.Serialization; namespace System.Reflection.TypeLoading { /// <summary> /// Base class for all Module objects created by a MetadataLoadContext. /// </summary> internal abstract partial class RoModule : Module { private readonly string _fullyQualifiedName; internal const string FullyQualifiedNameForModulesLoadedFromByteArrays = "<Unknown>"; internal RoModule(string fullyQualifiedName) : base() { Debug.Assert(fullyQualifiedName != null); _fullyQualifiedName = fullyQualifiedName; } public sealed override string ToString() => Loader.GetDisposedString() ?? base.ToString(); public sealed override Assembly Assembly => GetRoAssembly(); internal abstract RoAssembly GetRoAssembly(); internal const string UnknownStringMessageInRAF = "Returns <Unknown> for modules with no file path"; #if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public sealed override string FullyQualifiedName => _fullyQualifiedName; public abstract override int MDStreamVersion { get; } public abstract override int MetadataToken { get; } public abstract override Guid ModuleVersionId { get; } #if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public sealed override string Name { get { string s = FullyQualifiedName; int i = s.LastIndexOf(Path.DirectorySeparatorChar); if (i == -1) return s; return s.Substring(i + 1); } } public abstract override string ScopeName { get; } public sealed override IList<CustomAttributeData> GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); public abstract override IEnumerable<CustomAttributeData> CustomAttributes { get; } public sealed override object[] GetCustomAttributes(bool inherit) => throw new InvalidOperationException(SR.Arg_ReflectionOnlyCA); public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new InvalidOperationException(SR.Arg_ReflectionOnlyCA); public sealed override bool IsDefined(Type attributeType, bool inherit) => throw new InvalidOperationException(SR.Arg_ReflectionOnlyCA); public abstract override FieldInfo? GetField(string name, BindingFlags bindingAttr); public abstract override FieldInfo[] GetFields(BindingFlags bindingFlags); public abstract override MethodInfo[] GetMethods(BindingFlags bindingFlags); protected abstract override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers); #if NET [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] #endif public sealed override void GetObjectData(SerializationInfo info, StreamingContext context) => throw new NotSupportedException(); public abstract override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine); public abstract override Type[] GetTypes(); internal abstract IEnumerable<RoType>? GetDefinedRoTypes(); public abstract override bool IsResource(); public sealed override FieldInfo ResolveField(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments) => throw new NotSupportedException(SR.NotSupported_ResolvingTokens); public sealed override MemberInfo ResolveMember(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments) => throw new NotSupportedException(SR.NotSupported_ResolvingTokens); public sealed override MethodBase ResolveMethod(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments) => throw new NotSupportedException(SR.NotSupported_ResolvingTokens); public sealed override byte[] ResolveSignature(int metadataToken) => throw new NotSupportedException(SR.NotSupported_ResolvingTokens); public sealed override string ResolveString(int metadataToken) => throw new NotSupportedException(SR.NotSupported_ResolvingTokens); public sealed override Type ResolveType(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments) => throw new NotSupportedException(SR.NotSupported_ResolvingTokens); public sealed override Type? GetType(string className, bool throwOnError, bool ignoreCase) { // // This looks bogus and against the intended meaning of the api but it's pretty close to the .NET Framework behavior. // The .NET Framework Module.GetType() will search the entire assembly when encounting a non assembly-qualified type name but // *only* as long as it's a generic type argument, not the top level type. If you specify the name of a type in a // different module as the top level type, this api returns null (even if throwOnError is specified as true!) // Type type = Assembly.GetType(className, throwOnError: throwOnError, ignoreCase: ignoreCase)!; if (type.Module != this) { // We should throw if throwOnError == true, but .NET Framework doesn't so we'll keep the same behavior for the few people using this. return null; } return type; } /// <summary> /// Helper routine for the more general Module.GetType() family of apis. Also used in typeRef resolution. /// /// Resolves top-level named types only. No nested types. No constructed types. The input name must not be escaped. /// /// If a type is not contained or forwarded from the module, this method returns null (does not throw.) /// This supports the "throwOnError: false" behavior of Module.GetType(string, bool). /// </summary> internal RoDefinitionType? GetTypeCore(ReadOnlySpan<byte> ns, ReadOnlySpan<byte> name, bool ignoreCase, out Exception? e) { if (ignoreCase) throw new NotSupportedException(SR.NotSupported_CaseInsensitive); int hashCode = GetTypeCoreCache.ComputeHashCode(name); if (!_getTypeCoreCache.TryGet(ns, name, hashCode, out RoDefinitionType? type)) { type = GetTypeCoreNoCache(ns, name, out e) ?? new RoExceptionType(ns, name, e); _getTypeCoreCache.GetOrAdd(ns, name, hashCode, type); // Type objects are unified independently of this cache so no need to check if we won the race to cache this Type } if (type is RoExceptionType exceptionType) { e = exceptionType.Exception; return null; } e = null; return type; } protected abstract RoDefinitionType? GetTypeCoreNoCache(ReadOnlySpan<byte> ns, ReadOnlySpan<byte> name, out Exception? e); internal readonly GetTypeCoreCache _getTypeCoreCache = new GetTypeCoreCache(); internal MetadataLoadContext Loader => GetRoAssembly().Loader; } }