|
// 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.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using CultureInfo = System.Globalization.CultureInfo;
namespace System.Reflection.Emit
{
internal enum TypeKind
{
IsArray = 1,
IsPointer = 2,
IsByRef = 3,
}
// This is a kind of Type object that will represent the compound expression of a parameter type or field type.
internal sealed partial class SymbolType : TypeInfo
{
#region Data Members
#region Fields need to be kept in order
// For Mono runtime its important to keep this declaration order in sync with MonoReflectionSymbolType struct in object-internals.h
internal Type _baseType = null!;
internal TypeKind _typeKind;
internal int _rank; // count of dimension
#endregion
// If LowerBound and UpperBound is equal, that means one element.
// If UpperBound is less than LowerBound, then the size is not specified.
internal int[] _iaLowerBound;
internal int[] _iaUpperBound; // count of dimension
private string? _format; // format string to form the full name.
private bool _isSzArray = true;
#endregion
public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null) return false;
return IsAssignableFrom(typeInfo.AsType());
}
#region Static Members
internal static Type? FormCompoundType(string? format, Type baseType, int curIndex)
{
// This function takes a string to describe the compound type, such as "[,][]", and a baseType.
//
// Example: [2..4] - one dimension array with lower bound 2 and size of 3
// Example: [3, 5, 6] - three dimension array with lower bound 3, 5, 6
// Example: [-3, ] [] - one dimensional array of two dimensional array (with lower bound -3 for
// the first dimension)
// Example: []* - pointer to a one dimensional array
// Example: *[] - one dimensional array. The element type is a pointer to the baseType
// Example: []& - ByRef of a single dimensional array. Only one & is allowed and it must appear the last!
// Example: [?] - Array with unknown bound
SymbolType symbolType;
int iLowerBound;
int iUpperBound;
if (format == null || curIndex == format.Length)
{
// we have consumed all of the format string
return baseType;
}
if (format[curIndex] == '&')
{
// ByRef case
symbolType = new SymbolType(baseType, TypeKind.IsByRef);
symbolType.SetFormat(format, curIndex, 1);
curIndex++;
if (curIndex != format.Length)
// ByRef has to be the last char!!
throw new ArgumentException(SR.Argument_BadSigFormat);
return symbolType;
}
if (format[curIndex] == '[')
{
// Array type.
symbolType = new SymbolType(baseType, TypeKind.IsArray);
int startIndex = curIndex;
curIndex++;
iLowerBound = 0;
iUpperBound = -1;
// Example: [2..4] - one dimension array with lower bound 2 and size of 3
// Example: [3, 5, 6] - three dimension array with lower bound 3, 5, 6
// Example: [-3, ] [] - one dimensional array of two dimensional array (with lower bound -3 sepcified)
while (format[curIndex] != ']')
{
if (format[curIndex] == '*')
{
symbolType._isSzArray = false;
curIndex++;
}
// consume, one dimension at a time
if (char.IsAsciiDigit(format[curIndex]) || format[curIndex] == '-')
{
bool isNegative = false;
if (format[curIndex] == '-')
{
isNegative = true;
curIndex++;
}
// lower bound is specified. Consume the low bound
while (char.IsAsciiDigit(format[curIndex]))
{
iLowerBound *= 10;
iLowerBound += format[curIndex] - '0';
curIndex++;
}
if (isNegative)
{
iLowerBound = 0 - iLowerBound;
}
// set the upper bound to be less than LowerBound to indicate that upper bound it not specified yet!
iUpperBound = iLowerBound - 1;
}
if (format[curIndex] == '.')
{
// upper bound is specified
// skip over ".."
curIndex++;
if (format[curIndex] != '.')
{
// bad format!! Throw exception
throw new ArgumentException(SR.Argument_BadSigFormat);
}
curIndex++;
// consume the upper bound
if (char.IsAsciiDigit(format[curIndex]) || format[curIndex] == '-')
{
bool isNegative = false;
iUpperBound = 0;
if (format[curIndex] == '-')
{
isNegative = true;
curIndex++;
}
// lower bound is specified. Consume the low bound
while (char.IsAsciiDigit(format[curIndex]))
{
iUpperBound *= 10;
iUpperBound += format[curIndex] - '0';
curIndex++;
}
if (isNegative)
{
iUpperBound = 0 - iUpperBound;
}
if (iUpperBound < iLowerBound)
{
// User specified upper bound less than lower bound, this is an error.
// Throw error exception.
throw new ArgumentException(SR.Argument_BadSigFormat);
}
}
}
if (format[curIndex] == ',')
{
// We have more dimension to deal with.
// now set the lower bound, the size, and increase the dimension count!
curIndex++;
symbolType.SetBounds(iLowerBound, iUpperBound);
// clear the lower and upper bound information for next dimension
iLowerBound = 0;
iUpperBound = -1;
}
else if (format[curIndex] != ']')
{
throw new ArgumentException(SR.Argument_BadSigFormat);
}
}
// The last dimension information
symbolType.SetBounds(iLowerBound, iUpperBound);
// skip over ']'
curIndex++;
symbolType.SetFormat(format, startIndex, curIndex - startIndex);
return FormCompoundType(format, symbolType, curIndex);
}
else if (format[curIndex] == '*')
{
// pointer type.
symbolType = new SymbolType(baseType, TypeKind.IsPointer);
symbolType.SetFormat(format, curIndex, 1);
curIndex++;
return FormCompoundType(format, symbolType, curIndex);
}
return null;
}
#endregion
#region Constructor
internal SymbolType(Type baseType, TypeKind typeKind)
{
ArgumentNullException.ThrowIfNull(baseType);
_baseType = baseType;
_typeKind = typeKind;
_iaLowerBound = new int[4];
_iaUpperBound = new int[4];
}
#endregion
#region Internal Members
private void SetBounds(int lower, int upper)
{
// Increase the rank, set lower and upper bound
if (lower != 0 || upper != -1)
_isSzArray = false;
if (_iaLowerBound.Length <= _rank)
{
// resize the bound array
int[] iaTemp = new int[_rank * 2];
Array.Copy(_iaLowerBound, iaTemp, _rank);
_iaLowerBound = iaTemp;
Array.Copy(_iaUpperBound, iaTemp, _rank);
_iaUpperBound = iaTemp;
}
_iaLowerBound[_rank] = lower;
_iaUpperBound[_rank] = upper;
_rank++;
}
internal void SetFormat(string format, int curIndex, int length)
{
// Cache the text display format for this SymbolType
_format = format.Substring(curIndex, length);
}
#endregion
#region Type Overrides
public override bool IsTypeDefinition => false;
public override bool IsSZArray => _rank <= 1 && _isSzArray;
public override Type? GetNullableUnderlyingType() => null;
public override Type MakePointerType()
{
return FormCompoundType(_format + "*", _baseType, 0)!;
}
public override Type MakeByRefType()
{
return FormCompoundType(_format + "&", _baseType, 0)!;
}
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public override Type MakeArrayType()
{
return FormCompoundType(_format + "[]", _baseType, 0)!;
}
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public override Type MakeArrayType(int rank)
{
string s = FormatRank(rank);
SymbolType? st = FormCompoundType(_format + s, _baseType, 0) as SymbolType;
return st!;
}
internal static string FormatRank(int rank)
{
if (rank <= 0)
{
throw new IndexOutOfRangeException();
}
return rank == 1 ? "[*]" : "[" + new string(',', rank - 1) + "]";
}
public override int GetArrayRank()
{
if (!IsArray)
throw new ArgumentException(SR.Argument_HasToBeArrayClass);
return _rank;
}
public override Guid GUID => throw new NotSupportedException(SR.NotSupported_NonReflectedType);
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields |
DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties |
DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target,
object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
public override Module Module
{
get
{
Type baseType;
for (baseType = _baseType; baseType is SymbolType; baseType = ((SymbolType)baseType)._baseType) ;
return baseType.Module;
}
}
public override Assembly Assembly
{
get
{
Type baseType;
for (baseType = _baseType; baseType is SymbolType; baseType = ((SymbolType)baseType)._baseType) ;
return baseType.Assembly;
}
}
public override RuntimeTypeHandle TypeHandle => throw new NotSupportedException(SR.NotSupported_NonReflectedType);
public override string Name
{
get
{
Type baseType;
string? sFormat = _format;
for (baseType = _baseType; baseType is SymbolType; baseType = ((SymbolType)baseType)._baseType)
sFormat = ((SymbolType)baseType)._format + sFormat;
return baseType.Name + sFormat;
}
}
public override string? FullName => TypeNameBuilder.ToString(this, TypeNameBuilder.Format.FullName);
public override string? AssemblyQualifiedName => TypeNameBuilder.ToString(this, TypeNameBuilder.Format.AssemblyQualifiedName);
public override string ToString()
{
return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.ToString)!;
}
public override string? Namespace => _baseType.Namespace;
public override Type BaseType => typeof(Array);
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder? binder,
CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder,
CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
public override FieldInfo GetField(string name, BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
public override FieldInfo[] GetFields(BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
public override Type GetInterface(string name, bool ignoreCase)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
public override Type[] GetInterfaces()
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)]
public override EventInfo[] GetEvents()
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder,
Type? returnType, Type[]? types, ParameterModifier[]? modifiers)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
public override Type[] GetNestedTypes(BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
public override Type GetNestedType(string name, BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(GetAllMembersInternal)]
public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(GetAllMembersInternal)]
public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
private const DynamicallyAccessedMemberTypes GetAllMembersInternal = DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields |
DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents |
DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties |
DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors |
DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type interfaceType)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
public override EventInfo[] GetEvents(BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
protected override TypeAttributes GetAttributeFlagsImpl()
{
// Return the attribute flags of the base type?
Type baseType;
for (baseType = _baseType; baseType is SymbolType; baseType = ((SymbolType)baseType)._baseType) ;
return baseType.Attributes;
}
protected override bool IsArrayImpl()
{
return _typeKind == TypeKind.IsArray;
}
protected override bool IsPointerImpl()
{
return _typeKind == TypeKind.IsPointer;
}
protected override bool IsByRefImpl()
{
return _typeKind == TypeKind.IsByRef;
}
protected override bool IsPrimitiveImpl()
{
return false;
}
protected override bool IsValueTypeImpl()
{
return false;
}
protected override bool IsCOMObjectImpl()
{
return false;
}
public override bool IsConstructedGenericType => false;
public override Type? GetElementType()
{
return _baseType;
}
protected override bool HasElementTypeImpl()
{
return _baseType != null;
}
public override Type UnderlyingSystemType => this;
public override object[] GetCustomAttributes(bool inherit)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
public override bool IsDefined(Type attributeType, bool inherit)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}
#endregion
}
}
|