|
// 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.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace System.Reflection
{
internal sealed partial class RuntimeModule : Module
{
#region Data Members
#pragma warning disable CA1823, 169
// If you add any data members, you need to update the native declaration ReflectModuleBaseObject.
private RuntimeType m_runtimeType;
private readonly RuntimeAssembly m_runtimeAssembly;
private readonly IntPtr m_pData;
#pragma warning restore CA1823, 169
#endregion
internal RuntimeModule() { throw new NotSupportedException(); }
#region Module overrides
private static RuntimeTypeHandle[]? ConvertToTypeHandleArray(Type[]? genericArguments)
{
if (genericArguments == null)
return null;
int size = genericArguments.Length;
RuntimeTypeHandle[] typeHandleArgs = new RuntimeTypeHandle[size];
for (int i = 0; i < size; i++)
{
Type? typeArg = genericArguments[i]?.UnderlyingSystemType;
if (typeArg is not System.RuntimeType)
throw new ArgumentException(SR.Argument_InvalidGenericInstArray);
typeHandleArgs[i] = typeArg.TypeHandle;
}
return typeHandleArgs;
}
[RequiresUnreferencedCode("Trimming changes metadata tokens")]
public override byte[] ResolveSignature(int metadataToken)
{
MetadataToken tk = new MetadataToken(metadataToken);
if (!MetadataImport.IsValidToken(tk))
throw new ArgumentOutOfRangeException(nameof(metadataToken),
SR.Format(SR.Argument_InvalidToken, tk, this));
if (!tk.IsMemberRef && !tk.IsMethodDef && !tk.IsTypeSpec && !tk.IsSignature && !tk.IsFieldDef)
throw new ArgumentException(SR.Format(SR.Argument_InvalidToken, tk, this),
nameof(metadataToken));
ConstArray signature;
if (tk.IsMemberRef)
signature = MetadataImport.GetMemberRefProps(metadataToken);
else
signature = MetadataImport.GetSignatureFromToken(metadataToken);
byte[] sig = new byte[signature.Length];
for (int i = 0; i < signature.Length; i++)
sig[i] = signature[i];
return sig;
}
[RequiresUnreferencedCode("Trimming changes metadata tokens")]
public override MethodBase? ResolveMethod(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments)
{
try
{
MetadataToken tk = new MetadataToken(metadataToken);
if (!tk.IsMethodDef && !tk.IsMethodSpec)
{
if (!tk.IsMemberRef)
throw new ArgumentException(SR.Format(SR.Argument_ResolveMethod, tk, this),
nameof(metadataToken));
unsafe
{
ConstArray sig = MetadataImport.GetMemberRefProps(tk);
if (*(MdSigCallingConvention*)sig.Signature == MdSigCallingConvention.Field)
throw new ArgumentException(SR.Format(SR.Argument_ResolveMethod, tk, this),
nameof(metadataToken));
}
}
RuntimeTypeHandle[]? typeArgs = null;
RuntimeTypeHandle[]? methodArgs = null;
if (genericTypeArguments?.Length > 0)
{
typeArgs = ConvertToTypeHandleArray(genericTypeArguments);
}
if (genericMethodArguments?.Length > 0)
{
methodArgs = ConvertToTypeHandleArray(genericMethodArguments);
}
ModuleHandle moduleHandle = new ModuleHandle(this);
IRuntimeMethodInfo methodHandle = moduleHandle.ResolveMethodHandle(tk, typeArgs, methodArgs).GetMethodInfo();
Type declaringType = RuntimeMethodHandle.GetDeclaringType(methodHandle);
if (declaringType.IsGenericType || declaringType.IsArray)
{
MetadataToken tkDeclaringType = new MetadataToken(MetadataImport.GetParentToken(tk));
if (tk.IsMethodSpec)
tkDeclaringType = new MetadataToken(MetadataImport.GetParentToken(tkDeclaringType));
declaringType = ResolveType(tkDeclaringType, genericTypeArguments, genericMethodArguments);
}
return RuntimeType.GetMethodBase(declaringType as RuntimeType, methodHandle);
}
catch (BadImageFormatException e)
{
throw new ArgumentException(SR.Argument_BadImageFormatExceptionResolve, e);
}
}
[RequiresUnreferencedCode("Trimming changes metadata tokens")]
private FieldInfo? ResolveLiteralField(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments)
{
MetadataToken tk = new MetadataToken(metadataToken);
if (!MetadataImport.IsValidToken(tk) || !tk.IsFieldDef)
throw new ArgumentOutOfRangeException(nameof(metadataToken),
SR.Format(SR.Argument_InvalidToken, tk, this));
int tkDeclaringType;
string fieldName = MetadataImport.GetName(tk).ToString();
tkDeclaringType = MetadataImport.GetParentToken(tk);
Type declaringType = ResolveType(tkDeclaringType, genericTypeArguments, genericMethodArguments);
try
{
return declaringType.GetField(fieldName,
BindingFlags.Static | BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.DeclaredOnly);
}
catch
{
throw new ArgumentException(SR.Format(SR.Argument_ResolveField, tk, this), nameof(metadataToken));
}
}
[RequiresUnreferencedCode("Trimming changes metadata tokens")]
public override FieldInfo? ResolveField(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments)
{
try
{
MetadataToken tk = new MetadataToken(metadataToken);
if (!MetadataImport.IsValidToken(tk))
throw new ArgumentOutOfRangeException(nameof(metadataToken),
SR.Format(SR.Argument_InvalidToken, tk, this));
RuntimeTypeHandle[]? typeArgs = null;
RuntimeTypeHandle[]? methodArgs = null;
if (genericTypeArguments?.Length > 0)
{
typeArgs = ConvertToTypeHandleArray(genericTypeArguments);
}
if (genericMethodArguments?.Length > 0)
{
methodArgs = ConvertToTypeHandleArray(genericMethodArguments);
}
ModuleHandle moduleHandle = new ModuleHandle(this);
if (!tk.IsFieldDef)
{
if (!tk.IsMemberRef)
throw new ArgumentException(SR.Format(SR.Argument_ResolveField, tk, this),
nameof(metadataToken));
unsafe
{
ConstArray sig = MetadataImport.GetMemberRefProps(tk);
if (*(MdSigCallingConvention*)sig.Signature != MdSigCallingConvention.Field)
throw new ArgumentException(SR.Format(SR.Argument_ResolveField, tk, this),
nameof(metadataToken));
}
}
IRuntimeFieldInfo fieldHandle = moduleHandle.ResolveFieldHandle(metadataToken, typeArgs, methodArgs).GetRuntimeFieldInfo();
RuntimeType declaringType = RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle.Value);
if (declaringType.IsGenericType || declaringType.IsArray)
{
int tkDeclaringType = MetadataImport.GetParentToken(metadataToken);
declaringType = (RuntimeType)ResolveType(tkDeclaringType, genericTypeArguments, genericMethodArguments);
}
return RuntimeType.GetFieldInfo(declaringType, fieldHandle);
}
catch (MissingFieldException)
{
return ResolveLiteralField(metadataToken, genericTypeArguments, genericMethodArguments);
}
catch (BadImageFormatException e)
{
throw new ArgumentException(SR.Argument_BadImageFormatExceptionResolve, e);
}
}
[RequiresUnreferencedCode("Trimming changes metadata tokens")]
public override Type ResolveType(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments)
{
try
{
MetadataToken tk = new MetadataToken(metadataToken);
if (tk.IsGlobalTypeDefToken)
throw new ArgumentException(SR.Format(SR.Argument_ResolveModuleType, tk), nameof(metadataToken));
if (!tk.IsTypeDef && !tk.IsTypeSpec && !tk.IsTypeRef)
throw new ArgumentException(SR.Format(SR.Argument_ResolveType, tk, this), nameof(metadataToken));
RuntimeTypeHandle[]? typeArgs = null;
RuntimeTypeHandle[]? methodArgs = null;
if (genericTypeArguments?.Length > 0)
{
typeArgs = ConvertToTypeHandleArray(genericTypeArguments);
}
if (genericMethodArguments?.Length > 0)
{
methodArgs = ConvertToTypeHandleArray(genericMethodArguments);
}
return GetModuleHandleImpl().ResolveTypeHandle(metadataToken, typeArgs, methodArgs).GetRuntimeType();
}
catch (BadImageFormatException e)
{
throw new ArgumentException(SR.Argument_BadImageFormatExceptionResolve, e);
}
}
[RequiresUnreferencedCode("Trimming changes metadata tokens")]
public override MemberInfo? ResolveMember(int metadataToken, Type[]? genericTypeArguments, Type[]? genericMethodArguments)
{
MetadataToken tk = new MetadataToken(metadataToken);
if (tk.IsProperty)
throw new ArgumentException(SR.InvalidOperation_PropertyInfoNotAvailable);
if (tk.IsEvent)
throw new ArgumentException(SR.InvalidOperation_EventInfoNotAvailable);
if (tk.IsMethodSpec || tk.IsMethodDef)
return ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
if (tk.IsFieldDef)
return ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
if (tk.IsTypeRef || tk.IsTypeDef || tk.IsTypeSpec)
return ResolveType(metadataToken, genericTypeArguments, genericMethodArguments);
if (tk.IsMemberRef)
{
if (!MetadataImport.IsValidToken(tk))
throw new ArgumentOutOfRangeException(nameof(metadataToken),
SR.Format(SR.Argument_InvalidToken, tk, this));
ConstArray sig = MetadataImport.GetMemberRefProps(tk);
unsafe
{
if (*(MdSigCallingConvention*)sig.Signature == MdSigCallingConvention.Field)
{
return ResolveField(tk, genericTypeArguments, genericMethodArguments);
}
else
{
return ResolveMethod(tk, genericTypeArguments, genericMethodArguments);
}
}
}
throw new ArgumentException(SR.Format(SR.Argument_ResolveMember, tk, this),
nameof(metadataToken));
}
[RequiresUnreferencedCode("Trimming changes metadata tokens")]
public override string ResolveString(int metadataToken)
{
MetadataToken tk = new MetadataToken(metadataToken);
if (!tk.IsString)
throw new ArgumentException(
SR.Format(SR.Argument_ResolveString, metadataToken, this));
if (!MetadataImport.IsValidToken(tk))
throw new ArgumentOutOfRangeException(nameof(metadataToken),
SR.Format(SR.Argument_InvalidToken, tk, this));
string str = MetadataImport.GetUserString(metadataToken) ??
throw new ArgumentException(SR.Format(SR.Argument_ResolveString, metadataToken, this));
return str;
}
public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
{
ModuleHandle.GetPEKind(this, out peKind, out machine);
}
public override int MDStreamVersion => ModuleHandle.GetMDStreamVersion(this);
#endregion
#region Protected Virtuals
[RequiresUnreferencedCode("Methods might be removed because Module methods can't currently be annotated for dynamic access.")]
protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder,
CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers)
{
return GetMethodInternal(name, bindingAttr, binder, callConvention, types, modifiers);
}
[RequiresUnreferencedCode("Methods might be removed because Module methods can't currently be annotated for dynamic access.")]
internal MethodInfo? GetMethodInternal(string name, BindingFlags bindingAttr, Binder? binder,
CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers)
{
if (RuntimeType == null)
return null;
if (types == null)
{
return RuntimeType.GetMethod(name, bindingAttr);
}
else
{
return RuntimeType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
}
}
#endregion
#region Internal Members
internal RuntimeType RuntimeType => m_runtimeType ??= ModuleHandle.GetModuleType(this);
internal MetadataImport MetadataImport => new MetadataImport(this);
#endregion
#region ICustomAttributeProvider Members
public override object[] GetCustomAttributes(bool inherit)
{
return CustomAttribute.GetCustomAttributes(this, (typeof(object) as RuntimeType)!);
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
ArgumentNullException.ThrowIfNull(attributeType);
if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType)
throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType));
return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
}
public override bool IsDefined(Type attributeType, bool inherit)
{
ArgumentNullException.ThrowIfNull(attributeType);
if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType)
throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType));
return CustomAttribute.IsDefined(this, attributeRuntimeType);
}
public override IList<CustomAttributeData> GetCustomAttributesData()
{
return RuntimeCustomAttributeData.GetCustomAttributesInternal(this);
}
#endregion
#region Public Virtuals
[Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new PlatformNotSupportedException();
}
[RequiresUnreferencedCode("Types might be removed by trimming. If the type name is a string literal, consider using Type.GetType instead.")]
public override Type? GetType(
string className, // throw on null strings regardless of the value of "throwOnError"
bool throwOnError, bool ignoreCase)
{
ArgumentException.ThrowIfNullOrEmpty(className);
return TypeNameResolver.GetType(className, topLevelAssembly: Assembly,
throwOnError: throwOnError, ignoreCase: ignoreCase);
}
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeModule_GetFullyQualifiedName")]
private static partial void GetFullyQualifiedName(QCallModule module, StringHandleOnStack retString);
[RequiresAssemblyFiles(UnknownStringMessageInRAF)]
internal string GetFullyQualifiedName()
{
string? fullyQualifiedName = null;
RuntimeModule thisAsLocal = this;
GetFullyQualifiedName(new QCallModule(ref thisAsLocal), new StringHandleOnStack(ref fullyQualifiedName));
return fullyQualifiedName!;
}
[RequiresAssemblyFiles(UnknownStringMessageInRAF)]
public override string FullyQualifiedName => GetFullyQualifiedName();
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeModule_GetTypes")]
private static partial void GetTypes(QCallModule module, ObjectHandleOnStack retTypes);
internal RuntimeType[] GetDefinedTypes()
{
RuntimeType[]? types = null;
RuntimeModule thisAsLocal = this;
GetTypes(new QCallModule(ref thisAsLocal), ObjectHandleOnStack.Create(ref types));
return types!;
}
[RequiresUnreferencedCode("Types might be removed")]
public override Type[] GetTypes() => GetDefinedTypes();
#endregion
#region Public Members
public override Guid ModuleVersionId
{
get
{
MetadataImport.GetScopeProps(out Guid mvid);
return mvid;
}
}
public override int MetadataToken => ModuleHandle.GetToken(this);
public override bool IsResource()
{
// CoreClr does not support resource-only modules.
return false;
}
[RequiresUnreferencedCode("Fields might be removed")]
public override FieldInfo[] GetFields(BindingFlags bindingFlags)
{
if (RuntimeType == null)
return Array.Empty<FieldInfo>();
return RuntimeType.GetFields(bindingFlags);
}
[RequiresUnreferencedCode("Fields might be removed")]
public override FieldInfo? GetField(string name, BindingFlags bindingAttr)
{
ArgumentNullException.ThrowIfNull(name);
return RuntimeType?.GetField(name, bindingAttr);
}
[RequiresUnreferencedCode("Methods might be removed")]
public override MethodInfo[] GetMethods(BindingFlags bindingFlags)
{
if (RuntimeType == null)
return Array.Empty<MethodInfo>();
return RuntimeType.GetMethods(bindingFlags);
}
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeModule_GetScopeName")]
private static partial void GetScopeName(QCallModule module, StringHandleOnStack retString);
public override string ScopeName
{
get
{
string? scopeName = null;
RuntimeModule thisAsLocal = this;
GetScopeName(new QCallModule(ref thisAsLocal), new StringHandleOnStack(ref scopeName));
return scopeName!;
}
}
[RequiresAssemblyFiles(UnknownStringMessageInRAF)]
public override string Name
{
get
{
string s = GetFullyQualifiedName();
int i = s.LastIndexOf(IO.Path.DirectorySeparatorChar);
if (i < 0)
return s;
return s.Substring(i + 1);
}
}
public override Assembly Assembly => GetRuntimeAssembly();
internal RuntimeAssembly GetRuntimeAssembly()
{
return m_runtimeAssembly;
}
private protected override ModuleHandle GetModuleHandleImpl()
{
return new ModuleHandle(this);
}
internal IntPtr GetUnderlyingNativeHandle()
{
return m_pData;
}
#endregion
}
}
|