Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,46 @@

namespace System.Reflection
{
internal readonly struct QCustomAttributeList(RuntimeModule module, int metadataToken)
{
public RuntimeModule Module { get; } = module;
public int MetadataToken { get; } = metadataToken;

public QCustomAttributeList(RuntimeType target)
: this(target.GetRuntimeModule(), target.MetadataToken) { }

public QCustomAttributeList(RuntimeFieldInfo target)
: this(target.GetRuntimeModule(), target.MetadataToken) { }

public QCustomAttributeList(RuntimeMethodInfo target)
: this(target.GetRuntimeModule(), target.MetadataToken) { }

public QCustomAttributeList(RuntimeConstructorInfo target)
: this(target.GetRuntimeModule(), target.MetadataToken) { }

public QCustomAttributeList(RuntimeEventInfo target)
: this(target.GetRuntimeModule(), target.MetadataToken) { }

public QCustomAttributeList(RuntimePropertyInfo target)
: this(target.GetRuntimeModule(), target.MetadataToken) { }

public QCustomAttributeList(RuntimeModule target)
: this(target, target.MetadataToken) { }

public QCustomAttributeList(RuntimeAssembly target)
: this((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target)) { }

public QCustomAttributeList(RuntimeParameterInfo target)
: this(target.GetRuntimeModule()!, target.MetadataToken) { }
}

internal sealed partial class RuntimeCustomAttributeData : CustomAttributeData
{
#region Private Static Methods
private static IList<CustomAttributeData> GetCustomAttributes(RuntimeModule module, int tkTarget)
private static IList<CustomAttributeData> GetCustomAttributes(QCustomAttributeList attributeList)
{
CustomAttributeRecord[] records = GetCustomAttributeRecords(module, tkTarget);
RuntimeModule module = attributeList.Module;
CustomAttributeRecord[] records = GetCustomAttributeRecords(module, attributeList.MetadataToken);
if (records.Length == 0)
{
return Array.Empty<CustomAttributeData>();
Expand Down Expand Up @@ -164,6 +198,22 @@ private static CustomAttributeEncodedArgument ParseCustomAttributeValue(
return arg;
}

private static CustomAttributeType ParseNamedArgumentTarget(
ref CustomAttributeDataParser parser, RuntimeModule module, out string? argumentName)
{
// Determine if a field or property.
CustomAttributeEncoding namedArgFieldOrProperty = parser.GetTag();
if (namedArgFieldOrProperty is not CustomAttributeEncoding.Field
&& namedArgFieldOrProperty is not CustomAttributeEncoding.Property)
{
throw new BadImageFormatException(SR.Arg_CustomAttributeFormatException);
}

CustomAttributeType argumentType = ParseCustomAttributeType(ref parser, module);
argumentName = parser.GetString();
return argumentType;
}

private static CustomAttributeType ParseCustomAttributeType(ref CustomAttributeDataParser parser, RuntimeModule module)
{
CustomAttributeEncoding arrayTag = CustomAttributeEncoding.Undefined;
Expand Down Expand Up @@ -278,6 +328,8 @@ public bool ValidateProlog()
return val == 0x0001;
}

public int GetNamedArgumentCount() => GetI2();

public string? GetString()
{
byte packedLengthBegin = PeekData(sizeof(byte))[0];
Expand Down Expand Up @@ -340,18 +392,20 @@ internal static unsafe partial class RuntimeCustomAttribute
{
internal static bool IsAttributeDefined(RuntimeModule decoratedModule, int decoratedMetadataToken, int attributeCtorToken)
{
return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, null, attributeCtorToken, false);
return IsCustomAttributeDefined(new QCustomAttributeList(decoratedModule, decoratedMetadataToken), null, attributeCtorToken: attributeCtorToken);
}

internal static bool IsCustomAttributeDefined(
RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType? attributeFilterType)
{
return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, attributeFilterType, 0, false);
return IsCustomAttributeDefined(new QCustomAttributeList(decoratedModule, decoratedMetadataToken), attributeFilterType);
}

private static bool IsCustomAttributeDefined(
RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType? attributeFilterType, int attributeCtorToken, bool mustBeInheritable)
QCustomAttributeList customAttributes, RuntimeType? attributeFilterType, bool mustBeInheritable = false, int attributeCtorToken = 0)
{
RuntimeModule decoratedModule = customAttributes.Module;
int decoratedMetadataToken = customAttributes.MetadataToken;
MetadataImport scope = decoratedModule.MetadataImport;

scope.EnumCustomAttributes(decoratedMetadataToken, out MetadataEnumResult attributeTokens);
Expand Down Expand Up @@ -408,11 +462,13 @@ private static bool IsCustomAttributeDefined(
"As such the reflection usage in this method will never fail as those methods/fields will be present.")]
private static void AddCustomAttributes(
ref ListBuilder<object> attributes,
RuntimeModule decoratedModule, int decoratedMetadataToken,
QCustomAttributeList customAttributes,
RuntimeType? attributeFilterType, bool mustBeInheritable,
// The derivedAttributes list must be passed by value so that it is not modified with the discovered attributes
ListBuilder<object> derivedAttributes)
{
RuntimeModule decoratedModule = customAttributes.Module;
int decoratedMetadataToken = customAttributes.MetadataToken;
CustomAttributeRecord[] car = RuntimeCustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken);

if (attributeFilterType is null && car.Length == 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,59 @@
using System.Reflection;
using System.Runtime.InteropServices;

using System.Reflection.Runtime.EventInfos;
using System.Reflection.Runtime.FieldInfos;
using System.Reflection.Runtime.General;
using System.Reflection.Runtime.MethodInfos;
using System.Reflection.Runtime.MethodInfos.NativeFormat;
using System.Reflection.Runtime.Modules;
using System.Reflection.Runtime.PropertyInfos;
using System.Reflection.Runtime.TypeInfos;
using System.Reflection.Runtime.TypeInfos.NativeFormat;

using Internal.Metadata.NativeFormat;

namespace System.Reflection
{
internal readonly struct QCustomAttributeList(MetadataReader? reader, CustomAttributeHandleCollection handles)
{
public MetadataReader? Reader { get; } = reader;
public CustomAttributeHandleCollection Handles { get; } = handles;

public QCustomAttributeList(RuntimeType target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }

public QCustomAttributeList(RuntimeFieldInfo target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }

public QCustomAttributeList(RuntimeMethodInfo target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }

public QCustomAttributeList(RuntimeConstructorInfo target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }

public QCustomAttributeList(RuntimeEventInfo target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }

public QCustomAttributeList(RuntimePropertyInfo target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }

public QCustomAttributeList(RuntimeModule target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }

public QCustomAttributeList(RuntimeAssembly target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }

public QCustomAttributeList(RuntimeParameterInfo target)
: this(target.GetMetadataReader(), target.GetCustomAttributeHandles()) { }
}

internal sealed partial class RuntimeCustomAttributeData : CustomAttributeData
{
internal static IList<CustomAttributeData> GetCustomAttributes(
MetadataReader? reader, CustomAttributeHandleCollection customAttributeHandles)
private static IList<CustomAttributeData> GetCustomAttributes(QCustomAttributeList attributeList)
{
MetadataReader? reader = attributeList.Reader;
CustomAttributeHandleCollection customAttributeHandles = attributeList.Handles;
if (reader is null || customAttributeHandles.Count == 0)
return Array.Empty<CustomAttributeData>();

Expand Down Expand Up @@ -145,6 +182,22 @@ public readonly partial struct CustomAttributeTypedArgument

internal sealed partial class CustomAttributeEncodedArgument
{
private static CustomAttributeEncodedArgument ParseCustomAttributeValue(
ref CustomAttributeDataParser parser, CustomAttributeType type, MetadataReader _)
{
return parser.ParseArgument(type);
}

private static CustomAttributeType ParseNamedArgumentTarget(
ref CustomAttributeDataParser parser, MetadataReader module, out string? argumentName)
{
NamedArgument namedArgument = parser.GetNamedArgument();
RuntimeType argumentType = (RuntimeType)namedArgument.Type.Resolve(module, default).ToType();
CustomAttributeType type = new CustomAttributeType(argumentType);
argumentName = namedArgument.Name.GetString(module);
return type;
}

internal static object? ParseValue(MetadataReader reader, Handle value, RuntimeType argumentType)
{
try
Expand All @@ -162,20 +215,58 @@ internal sealed partial class CustomAttributeEncodedArgument
/// <summary>
/// Used to parse NativeFormat custom attribute data.
/// </summary>
private readonly struct CustomAttributeDataParser
private struct CustomAttributeDataParser
{
private readonly CustomAttribute _attribute;
private readonly MetadataReader _reader;
private HandleCollection.Enumerator _fixedArguments;
private NamedArgumentHandleCollection.Enumerator _namedArguments;
private Handle _namedArgumentValue;
private bool _parsingNamedArguments;

public CustomAttributeDataParser(CustomAttribute attribute, MetadataReader reader)
{
_attribute = attribute;
_reader = reader;
}

public CustomAttribute Attribute => _attribute;
public bool ValidateProlog()
{
if (_reader is null)
return false;

public bool ValidateProlog() => _reader is not null;
_fixedArguments = _attribute.FixedArguments.GetEnumerator();
return true;
}

public int GetNamedArgumentCount() => _attribute.NamedArguments.Count;

public NamedArgument GetNamedArgument()
{
if (!_parsingNamedArguments)
{
_namedArguments = _attribute.NamedArguments.GetEnumerator();
_parsingNamedArguments = true;
}

if (!_namedArguments.MoveNext())
throw new BadImageFormatException();

NamedArgument namedArgument = _namedArguments.Current.GetNamedArgument(_reader);
_namedArgumentValue = namedArgument.Value;
return namedArgument;
}

public CustomAttributeEncodedArgument ParseArgument(CustomAttributeType type)
{
if (_parsingNamedArguments)
return ParseValue(_namedArgumentValue, type);

if (!_fixedArguments.MoveNext())
throw new BadImageFormatException();

return ParseValue(_fixedArguments.Current, type);
}

public CustomAttributeEncodedArgument ParseValue(Handle value, CustomAttributeType type)
{
Expand Down Expand Up @@ -506,16 +597,16 @@ private static CustomAttributeType CreateArrayType(CustomAttributeEncoding eleme
internal static partial class RuntimeCustomAttribute
{
private static bool IsCustomAttributeDefined(
MetadataReader? reader,
CustomAttributeHandleCollection customAttributeHandles,
QCustomAttributeList customAttributes,
RuntimeType attributeFilterType,
bool mustBeInheritable = false)
{
MetadataReader? reader = customAttributes.Reader;
if (reader is null)
return false;

ListBuilder<object> derivedAttributes = default;
foreach (CustomAttributeHandle customAttributeHandle in customAttributeHandles)
foreach (CustomAttributeHandle customAttributeHandle in customAttributes.Handles)
{
CustomAttribute customAttribute = customAttributeHandle.GetCustomAttribute(reader);
if (FilterCustomAttributeRecord(
Expand Down Expand Up @@ -558,16 +649,16 @@ private static bool FilterCustomAttributeRecord(
"attribute instantiation which is present in the code linker has analyzed.")]
private static void AddCustomAttributes(
ref ListBuilder<object> attributes,
MetadataReader? reader,
CustomAttributeHandleCollection customAttributeHandles,
QCustomAttributeList customAttributes,
RuntimeType? attributeFilterType,
bool mustBeInheritable,
ListBuilder<object> derivedAttributes)
{
MetadataReader? reader = customAttributes.Reader;
if (reader is null)
return;

foreach (CustomAttributeHandle customAttributeHandle in customAttributeHandles)
foreach (CustomAttributeHandle customAttributeHandle in customAttributes.Handles)
{
CustomAttribute customAttribute = customAttributeHandle.GetCustomAttribute(reader);

Expand Down
Loading
Loading