private List <CustomAttribute> HandleCustomAttributes(Cts.Ecma.EcmaModule module, Ecma.CustomAttributeHandleCollection attributes) { List <CustomAttribute> customAttributes = new List <CustomAttribute>(attributes.Count); var attributeTypeProvider = new Cts.Ecma.CustomAttributeTypeProvider(module); Ecma.MetadataReader reader = module.MetadataReader; foreach (var attributeHandle in attributes) { if (!_policy.GeneratesMetadata(module, attributeHandle)) { continue; } Ecma.CustomAttribute attribute = reader.GetCustomAttribute(attributeHandle); // TODO-NICE: We can intern the attributes based on the CA constructor and blob bytes Cts.MethodDesc constructor = module.GetMethod(attribute.Constructor); var decodedValue = attribute.DecodeValue(attributeTypeProvider); customAttributes.Add(HandleCustomAttribute(constructor, decodedValue)); } return(customAttributes); }
static decimal?TryDecodeDecimalConstantAttribute(MetadataModule module, System.Reflection.Metadata.CustomAttribute attribute) { var attrValue = attribute.DecodeValue(module.TypeProvider); if (attrValue.FixedArguments.Length != 5) { return(null); } // DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low) // Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required. if (!(attrValue.FixedArguments[0].Value is byte scale && attrValue.FixedArguments[1].Value is byte sign)) { return(null); } unchecked { if (attrValue.FixedArguments[2].Value is uint hi && attrValue.FixedArguments[3].Value is uint mid && attrValue.FixedArguments[4].Value is uint lo) { return(new decimal((int)lo, (int)mid, (int)hi, sign != 0, scale)); } } { if (attrValue.FixedArguments[2].Value is int hi && attrValue.FixedArguments[3].Value is int mid && attrValue.FixedArguments[4].Value is int lo) { return(new decimal(lo, mid, hi, sign != 0, scale)); } } return(null); }
private List <CustomAttribute> HandleCustomAttributes(Cts.Ecma.EcmaModule module, Ecma.CustomAttributeHandleCollection attributes) { List <CustomAttribute> customAttributes = new List <CustomAttribute>(attributes.Count); var attributeTypeProvider = new Cts.Ecma.CustomAttributeTypeProvider(module); foreach (var attributeHandle in attributes) { Ecma.MetadataReader reader = module.MetadataReader; Ecma.CustomAttribute attribute = reader.GetCustomAttribute(attributeHandle); // TODO-NICE: We can intern the attributes based on the CA constructor and blob bytes try { Cts.MethodDesc constructor = module.GetMethod(attribute.Constructor); var decodedValue = attribute.DecodeValue(attributeTypeProvider); if (IsBlockedCustomAttribute(constructor, decodedValue)) { continue; } customAttributes.Add(HandleCustomAttribute(constructor, decodedValue)); } catch (Cts.TypeSystemException) { // TODO: We should emit unresolvable custom attributes instead of skipping these } } return(customAttributes); }
/// <summary> /// This method will return a list of parameter values for the custom attribute. /// </summary> /// <remarks> /// Currently, this only works for string values /// </remarks> public static ImmutableArray<string> GetParameterValues(this MetadataReader metadataReader, CustomAttribute customAttribute) { if (customAttribute.Constructor.Kind != HandleKind.MemberReference) { throw new InvalidOperationException(); } var ctor = metadataReader.GetMemberReference((MemberReferenceHandle)customAttribute.Constructor); var signature = SignatureDecoder.DecodeMethodSignature(ctor.Signature, new StringParameterValueTypeProvider(metadataReader, customAttribute.Value)); return signature.ParameterTypes; }
/// <summary> /// Gets the fixed (required) string arguments of a custom attribute. /// Only attributes that have only fixed string arguments. /// </summary> private static List<string> GetFixedStringArguments(MetadataReader reader, CustomAttribute attribute) { // TODO: Nick Guerrera ([email protected]) hacked this method for temporary use. // There is a blob decoder feature in progress but it won't ship in time for our milestone. // Replace this method with the blob decoder feature when later it is availale. var signature = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor).Signature; var signatureReader = reader.GetBlobReader(signature); var valueReader = reader.GetBlobReader(attribute.Value); var arguments = new List<string>(); var prolog = valueReader.ReadUInt16(); if (prolog != 1) { // Invalid custom attribute prolog return arguments; } var header = signatureReader.ReadSignatureHeader(); if (header.Kind != SignatureKind.Method || header.IsGeneric) { // Invalid custom attribute constructor signature return arguments; } int parameterCount; if (!signatureReader.TryReadCompressedInteger(out parameterCount)) { // Invalid custom attribute constructor signature return arguments; } var returnType = signatureReader.ReadSignatureTypeCode(); if (returnType != SignatureTypeCode.Void) { // Invalid custom attribute constructor signature return arguments; } for (int i = 0; i < parameterCount; i++) { var signatureTypeCode = signatureReader.ReadSignatureTypeCode(); if (signatureTypeCode == SignatureTypeCode.String) { // Custom attribute constructor must take only strings arguments.Add(valueReader.ReadSerializedString()); } } return arguments; }
/// <summary> /// Gets the type of the attribute. /// </summary> public static EntityHandle GetAttributeType(this SRM.CustomAttribute attribute, MetadataReader reader) { switch (attribute.Constructor.Kind) { case HandleKind.MethodDefinition: var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor); return(md.GetDeclaringType()); case HandleKind.MemberReference: var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor); return(mr.Parent); default: throw new BadImageFormatException("Unexpected token kind for attribute constructor: " + attribute.Constructor.Kind); } }
public static Handle GetAttributeTypeHandle(this MetadataReader metadataReader, CustomAttribute customAttribute) { Handle attributeTypeHandle; var ctor = customAttribute.Constructor; if (ctor.HandleType == HandleType.MemberReference) { var memberReferenceHandle = (MemberReferenceHandle)ctor; var memberReference = metadataReader.GetMemberReference(memberReferenceHandle); attributeTypeHandle = memberReference.Parent; } else { MethodHandle methodHandle = (MethodHandle)ctor; var method = metadataReader.GetMethod(methodHandle); attributeTypeHandle = metadataReader.GetDeclaringType(methodHandle); } return attributeTypeHandle; }
/// <summary>Gets the string argument value of an attribute with a single fixed string argument.</summary> /// <param name="reader">The metadata reader.</param> /// <param name="attr">The attribute.</param> /// <param name="value">The value parsed from the attribute, if it could be retrieved; otherwise, the value is left unmodified.</param> private static void GetStringAttributeArgumentValue(MetadataReader reader, CustomAttribute attr, ref string value) { EntityHandle ctorHandle = attr.Constructor; BlobHandle signature; switch (ctorHandle.Kind) { case HandleKind.MemberReference: signature = reader.GetMemberReference((MemberReferenceHandle)ctorHandle).Signature; break; case HandleKind.MethodDefinition: signature = reader.GetMethodDefinition((MethodDefinitionHandle)ctorHandle).Signature; break; default: // Unusual case, potentially invalid IL return; } BlobReader signatureReader = reader.GetBlobReader(signature); BlobReader valueReader = reader.GetBlobReader(attr.Value); const ushort Prolog = 1; // two-byte "prolog" defined by ECMA-335 (II.23.3) to be at the beginning of attribute value blobs if (valueReader.ReadUInt16() == Prolog) { SignatureHeader header = signatureReader.ReadSignatureHeader(); int parameterCount; if (header.Kind == SignatureKind.Method && // attr ctor must be a method !header.IsGeneric && // attr ctor must be non-generic signatureReader.TryReadCompressedInteger(out parameterCount) && // read parameter count parameterCount == 1 && // attr ctor must have 1 parameter signatureReader.ReadSignatureTypeCode() == SignatureTypeCode.Void && // attr ctor return type must be void signatureReader.ReadSignatureTypeCode() == SignatureTypeCode.String) // attr ctor first parameter must be string { value = valueReader.ReadSerializedString(); } } }
/// <summary>Gets the name of an attribute.</summary> /// <param name="reader">The metadata reader.</param> /// <param name="attr">The attribute.</param> /// <param name="typeNamespaceHandle">The namespace of the attribute.</param> /// <param name="typeNameHandle">The name of the attribute.</param> /// <returns>true if the name could be retrieved; otherwise, false.</returns> private static bool TryGetAttributeName(MetadataReader reader, CustomAttribute attr, out StringHandle typeNamespaceHandle, out StringHandle typeNameHandle) { EntityHandle ctorHandle = attr.Constructor; switch (ctorHandle.Kind) { case HandleKind.MemberReference: EntityHandle container = reader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; if (container.Kind == HandleKind.TypeReference) { TypeReference tr = reader.GetTypeReference((TypeReferenceHandle)container); typeNamespaceHandle = tr.Namespace; typeNameHandle = tr.Name; return true; } break; case HandleKind.MethodDefinition: MethodDefinition md = reader.GetMethodDefinition((MethodDefinitionHandle)ctorHandle); TypeDefinition td = reader.GetTypeDefinition(md.GetDeclaringType()); typeNamespaceHandle = td.Namespace; typeNameHandle = td.Name; return true; } // Unusual case, potentially invalid IL typeNamespaceHandle = default(StringHandle); typeNameHandle = default(StringHandle); return false; }
internal static bool IsKnownAttribute(this SRM.CustomAttribute attr, MetadataReader metadata, KnownAttribute attrType) { return(attr.GetAttributeType(metadata).IsKnownType(metadata, attrType)); }
private bool TryHandleExportAttribute(CustomAttribute customAttribute, Handle attributeTypeDefinitionHandle) { bool isInheritedExport = false; bool isExport = IsExportAttribute(attributeTypeDefinitionHandle, out isInheritedExport); if (!isExport) { return false; } var parent = customAttribute.Parent; switch (parent.Kind) { case HandleKind.TypeDefinition: var TypeDefinitionHandle = (TypeDefinitionHandle)parent; TypeInfo exportedTypeInfo = GetOrCreateTypeInfo(TypeDefinitionHandle); if (isInheritedExport) { //this.inheritedExportTypes.Add(TypeDefinitionHandle, true); //this.inheritedExportTypesByName.Add(exportedTypeInfo.FullName); //this.hasInheritedExports = true; } else { exportedTypeInfo.IsExported = true; } break; case HandleKind.PropertyDefinition: MemberInfo propertyInfo = GetOrAddPropertyInfo((PropertyDefinitionHandle)parent); this.AddExportedMember(propertyInfo); break; case HandleKind.MethodDefinition: MemberInfo methodInfo = GetOrAddMethodInfo((MethodDefinitionHandle)parent); this.AddExportedMember(methodInfo); break; case HandleKind.FieldDefinition: MemberInfo exportedFieldInfo = GetOrAddFieldInfo((FieldDefinitionHandle)parent); this.AddExportedMember(exportedFieldInfo); break; default: throw new NotImplementedException(); } return true; }
private bool TryHandleImportAttribute(CustomAttribute customAttribute, Handle attributeTypeDefinitionHandle) { bool isImport = IsImportAttribute(attributeTypeDefinitionHandle); if (!isImport) { return false; } var parent = customAttribute.Parent; switch (parent.Kind) { case HandleKind.PropertyDefinition: MemberInfo propertyInfo = GetOrAddPropertyInfo((PropertyDefinitionHandle)parent); this.AddImportedMember(propertyInfo); break; case HandleKind.FieldDefinition: MemberInfo fieldInfo = GetOrAddFieldInfo((FieldDefinitionHandle)parent); this.AddImportedMember(fieldInfo); break; case HandleKind.Parameter: // ignore Import attributes on parameters of importing constructors break; case HandleKind.MethodDefinition: case HandleKind.MethodImplementation: case HandleKind.MethodSpecification: default: throw new NotImplementedException(); } return true; }