Example #1
0
        private List<CustomAttributeHandle> GetCustomAttributes(MetadataReader reader, int token)
        {
            var attributes = new List<CustomAttributeHandle>();
            foreach (var caHandle in reader.GetCustomAttributes(new EntityHandle((uint)token)))
            {
                attributes.Add(caHandle);
            }

            return attributes;
        }
Example #2
0
        public void TestCustomAttributeDecoderUsingReflection()
        {
            Type type = typeof(HasAttributes);

            using (FileStream stream = File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(type.GetTypeInfo().Assembly)))
                using (PEReader peReader = new PEReader(stream))
                {
                    MetadataReader reader = peReader.GetMetadataReader();
                    CustomAttributeTypeProvider provider      = new CustomAttributeTypeProvider();
                    TypeDefinitionHandle        typeDefHandle = TestMetadataResolver.FindTestType(reader, type);

                    IList <CustomAttributeData> attributes = type.GetCustomAttributesData();

                    int i = 0;
                    foreach (CustomAttributeHandle attributeHandle in reader.GetCustomAttributes(typeDefHandle))
                    {
                        CustomAttribute attribute           = reader.GetCustomAttribute(attributeHandle);
                        CustomAttributeValue <string> value = attribute.DecodeValue(provider);
                        CustomAttributeData           reflectionAttribute = attributes[i++];

                        Assert.Equal(reflectionAttribute.ConstructorArguments.Count, value.FixedArguments.Length);
                        Assert.Equal(reflectionAttribute.NamedArguments.Count, value.NamedArguments.Length);

                        int j = 0;
                        foreach (CustomAttributeTypedArgument <string> arguments in value.FixedArguments)
                        {
                            Type t = reflectionAttribute.ConstructorArguments[j].ArgumentType;
                            Assert.Equal(TypeToString(t), arguments.Type);
                            if (t.IsArray && arguments.Value is not null)
                            {
                                ImmutableArray <CustomAttributeTypedArgument <string> > array = (ImmutableArray <CustomAttributeTypedArgument <string> >)(arguments.Value);
                                IList <CustomAttributeTypedArgument> refArray = (IList <CustomAttributeTypedArgument>)reflectionAttribute.ConstructorArguments[j].Value;
                                int k = 0;
                                foreach (CustomAttributeTypedArgument <string> element in array)
                                {
                                    if (refArray[k].ArgumentType.IsArray)
                                    {
                                        ImmutableArray <CustomAttributeTypedArgument <string> > innerArray = (ImmutableArray <CustomAttributeTypedArgument <string> >)(element.Value);
                                        IList <CustomAttributeTypedArgument> refInnerArray = (IList <CustomAttributeTypedArgument>)refArray[k].Value;
                                        int a = 0;
                                        foreach (CustomAttributeTypedArgument <string> el in innerArray)
                                        {
                                            if (refInnerArray[a].Value?.ToString() != el.Value?.ToString())
                                            {
                                                Assert.Equal(refInnerArray[a].Value, el.Value);
                                            }
                                            a++;
                                        }
                                    }
                                    else if (refArray[k].Value?.ToString() != element.Value?.ToString())
                                    {
                                        if (refArray[k].ArgumentType == typeof(Type)) // TODO: check if it is expected
                                        {
                                            Assert.Contains(refArray[k].Value.ToString(), element.Value.ToString());
                                        }
                                        else
                                        {
                                            Assert.Equal(refArray[k].Value, element.Value);
                                        }
                                    }
                                    k++;
                                }
                            }
                            else if (reflectionAttribute.ConstructorArguments[j].Value?.ToString() != arguments.Value?.ToString())
                            {
                                if (reflectionAttribute.ConstructorArguments[j].ArgumentType == typeof(Type))
                                {
                                    Assert.Contains(reflectionAttribute.ConstructorArguments[j].Value.ToString(), arguments.Value.ToString());
                                }
                                else
                                {
                                    Assert.Equal(reflectionAttribute.ConstructorArguments[j].Value, arguments.Value);
                                }
                            }
                            j++;
                        }
                        j = 0;
                        foreach (CustomAttributeNamedArgument <string> arguments in value.NamedArguments)
                        {
                            Type t = reflectionAttribute.NamedArguments[j].TypedValue.ArgumentType;
                            Assert.Equal(TypeToString(t), arguments.Type);
                            if (t.IsArray && arguments.Value is not null)
                            {
                                ImmutableArray <CustomAttributeTypedArgument <string> > array = (ImmutableArray <CustomAttributeTypedArgument <string> >)(arguments.Value);
                                IList <CustomAttributeTypedArgument> refArray = (IList <CustomAttributeTypedArgument>)reflectionAttribute.NamedArguments[j].TypedValue.Value;
                                int k = 0;
                                foreach (CustomAttributeTypedArgument <string> element in array)
                                {
                                    if (refArray[k].Value?.ToString() != element.Value?.ToString())
                                    {
                                        Assert.Equal(refArray[k].Value, element.Value);
                                    }
                                    k++;
                                }
                            }
                            else if (reflectionAttribute.NamedArguments[j].TypedValue.Value?.ToString() != arguments.Value?.ToString())
                            {
                                if (reflectionAttribute.NamedArguments[j].TypedValue.ArgumentType == typeof(Type)) // typeof operator used for named parameter, like [Test(TypeField = typeof(string))], check if it is expected
                                {
                                    Assert.Contains(reflectionAttribute.NamedArguments[j].TypedValue.Value.ToString(), arguments.Value.ToString());
                                }
                                else
                                {
                                    Assert.Equal(reflectionAttribute.NamedArguments[j].TypedValue.Value, arguments.Value);
                                }
                            }
                            j++;
                        }
                    }
                }
        }
Example #3
0
        public void TestCustomAttributeDecoder()
        {
            using (FileStream stream = File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(typeof(HasAttributes).GetTypeInfo().Assembly)))
                using (var peReader = new PEReader(stream))
                {
                    MetadataReader       reader        = peReader.GetMetadataReader();
                    var                  provider      = new CustomAttributeTypeProvider();
                    TypeDefinitionHandle typeDefHandle = TestMetadataResolver.FindTestType(reader, typeof(HasAttributes));

                    int i = 0;
                    foreach (CustomAttributeHandle attributeHandle in reader.GetCustomAttributes(typeDefHandle))
                    {
                        CustomAttribute attribute           = reader.GetCustomAttribute(attributeHandle);
                        CustomAttributeValue <string> value = attribute.DecodeValue(provider);

                        switch (i++)
                        {
                        case 0:
                            Assert.Empty(value.FixedArguments);
                            Assert.Empty(value.NamedArguments);
                            break;

                        case 1:
                            Assert.Equal(3, value.FixedArguments.Length);

                            Assert.Equal("string", value.FixedArguments[0].Type);
                            Assert.Equal("0", value.FixedArguments[0].Value);

                            Assert.Equal("int32", value.FixedArguments[1].Type);
                            Assert.Equal(1, value.FixedArguments[1].Value);

                            Assert.Equal("float64", value.FixedArguments[2].Type);
                            Assert.Equal(2.0, value.FixedArguments[2].Value);

                            Assert.Empty(value.NamedArguments);
                            break;

                        case 2:
                            Assert.Equal(3, value.NamedArguments.Length);

                            Assert.Equal(CustomAttributeNamedArgumentKind.Field, value.NamedArguments[0].Kind);
                            Assert.Equal("StringField", value.NamedArguments[0].Name);
                            Assert.Equal("string", value.NamedArguments[0].Type);
                            Assert.Equal("0", value.NamedArguments[0].Value);

                            Assert.Equal(CustomAttributeNamedArgumentKind.Field, value.NamedArguments[1].Kind);
                            Assert.Equal("Int32Field", value.NamedArguments[1].Name);
                            Assert.Equal("int32", value.NamedArguments[1].Type);
                            Assert.Equal(1, value.NamedArguments[1].Value);

                            Assert.Equal(CustomAttributeNamedArgumentKind.Property, value.NamedArguments[2].Kind);
                            Assert.Equal("SByteEnumArrayProperty", value.NamedArguments[2].Name);
                            Assert.Equal(typeof(SByteEnum).FullName + "[]", value.NamedArguments[2].Type);

                            var array = (ImmutableArray <CustomAttributeTypedArgument <string> >)(value.NamedArguments[2].Value);
                            Assert.Equal(1, array.Length);
                            Assert.Equal(typeof(SByteEnum).FullName, array[0].Type);
                            Assert.Equal((sbyte)SByteEnum.Value, array[0].Value);
                            break;

                        default:
                            // TODO: https://github.com/dotnet/runtime/issues/73593
                            // This method only tests first 3 attriubtes because the complete test 'TestCustomAttributeDecoderUsingReflection' fails on mono
                            // Leaving this hard coded test only for mono, until the issue fixed on mono
                            break;
                        }
                    }
                }
        }
Example #4
0
        public void TestCustomAttributeDecoder()
        {
            using (FileStream stream = File.OpenRead(typeof(HasAttributes).GetTypeInfo().Assembly.Location))
                using (var peReader = new PEReader(stream))
                {
                    MetadataReader       reader        = peReader.GetMetadataReader();
                    var                  provider      = new CustomAttributeTypeProvider();
                    TypeDefinitionHandle typeDefHandle = TestMetadataResolver.FindTestType(reader, typeof(HasAttributes));


                    int i = 0;
                    foreach (CustomAttributeHandle attributeHandle in reader.GetCustomAttributes(typeDefHandle))
                    {
                        CustomAttribute attribute           = reader.GetCustomAttribute(attributeHandle);
                        CustomAttributeValue <string> value = attribute.DecodeValue(provider);

                        switch (i++)
                        {
                        case 0:
                            Assert.Empty(value.FixedArguments);
                            Assert.Empty(value.NamedArguments);
                            break;

                        case 1:
                            Assert.Equal(3, value.FixedArguments.Length);

                            Assert.Equal("string", value.FixedArguments[0].Type);
                            Assert.Equal("0", value.FixedArguments[0].Value);

                            Assert.Equal("int32", value.FixedArguments[1].Type);
                            Assert.Equal(1, value.FixedArguments[1].Value);

                            Assert.Equal("float64", value.FixedArguments[2].Type);
                            Assert.Equal(2.0, value.FixedArguments[2].Value);

                            Assert.Empty(value.NamedArguments);
                            break;

                        case 2:
                            Assert.Equal(3, value.NamedArguments.Length);

                            Assert.Equal(CustomAttributeNamedArgumentKind.Field, value.NamedArguments[0].Kind);
                            Assert.Equal("StringField", value.NamedArguments[0].Name);
                            Assert.Equal("string", value.NamedArguments[0].Type);
                            Assert.Equal("0", value.NamedArguments[0].Value);

                            Assert.Equal(CustomAttributeNamedArgumentKind.Field, value.NamedArguments[1].Kind);
                            Assert.Equal("Int32Field", value.NamedArguments[1].Name);
                            Assert.Equal("int32", value.NamedArguments[1].Type);
                            Assert.Equal(1, value.NamedArguments[1].Value);

                            Assert.Equal(CustomAttributeNamedArgumentKind.Property, value.NamedArguments[2].Kind);
                            Assert.Equal("SByteEnumArrayProperty", value.NamedArguments[2].Name);
                            Assert.Equal(typeof(SByteEnum).FullName + "[]", value.NamedArguments[2].Type);

                            var array = (ImmutableArray <CustomAttributeTypedArgument <string> >)(value.NamedArguments[2].Value);
                            Assert.Equal(1, array.Length);
                            Assert.Equal(typeof(SByteEnum).FullName, array[0].Type);
                            Assert.Equal((sbyte)SByteEnum.Value, array[0].Value);
                            break;

                        default:
                            // TODO: https://github.com/dotnet/corefx/issues/6534
                            // The other cases are missing corresponding assertions. This needs some refactoring to
                            // be data-driven. A better approach would probably be to generically compare reflection
                            // CustomAttributeData to S.R.M CustomAttributeValue for every test attribute applied.
                            break;
                        }
                    }
                }
        }
Example #5
0
 public static CustomAttributeHandleCollection GetCustomAttributes(this EntityHandle handle, MetadataReader reader) => reader.GetCustomAttributes(handle);
        public static string DetectTargetFrameworkId(this MetadataReader metadata, string assemblyPath = null)
        {
            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }

            const string TargetFrameworkAttributeName = "System.Runtime.Versioning.TargetFrameworkAttribute";

            foreach (var h in metadata.GetCustomAttributes(Handle.AssemblyDefinition))
            {
                try
                {
                    var attribute = metadata.GetCustomAttribute(h);
                    if (attribute.GetAttributeType(metadata).GetFullTypeName(metadata).ToString() != TargetFrameworkAttributeName)
                    {
                        continue;
                    }
                    var blobReader = metadata.GetBlobReader(attribute.Value);
                    if (blobReader.ReadUInt16() == 0x0001)
                    {
                        return(blobReader.ReadSerializedString()?.Replace(" ", ""));
                    }
                }
                catch (BadImageFormatException)
                {
                    // ignore malformed attributes
                }
            }

            if (metadata.IsAssembly)
            {
                var thisAssemblyName = metadata.GetAssemblyDefinition().GetAssemblyName();
                switch (thisAssemblyName.Name)
                {
                case "mscorlib":
                    return($".NETFramework,Version=v{thisAssemblyName.Version.ToString(2)}");

                case "netstandard":
                    return($".NETStandard,Version=v{thisAssemblyName.Version.ToString(2)}");
                }
            }

            foreach (var h in metadata.AssemblyReferences)
            {
                try
                {
                    var r = metadata.GetAssemblyReference(h);
                    if (r.PublicKeyOrToken.IsNil)
                    {
                        continue;
                    }
                    string version;
                    switch (metadata.GetString(r.Name))
                    {
                    case "netstandard":
                        version = r.Version.ToString(2);
                        return($".NETStandard,Version=v{version}");

                    case "System.Runtime":
                        // System.Runtime.dll uses the following scheme:
                        // 4.2.0 => .NET Core 2.0
                        // 4.2.1 => .NET Core 2.1 / 3.0
                        // 4.2.2 => .NET Core 3.1
                        if (r.Version >= new Version(4, 2, 0))
                        {
                            version = "2.0";
                            if (r.Version >= new Version(4, 2, 1))
                            {
                                version = "3.0";
                            }
                            if (r.Version >= new Version(4, 2, 2))
                            {
                                version = "3.1";
                            }
                            return($".NETCoreApp,Version=v{version}");
                        }
                        else
                        {
                            continue;
                        }

                    case "mscorlib":
                        version = r.Version.ToString(2);
                        return($".NETFramework,Version=v{version}");
                    }
                }
                catch (BadImageFormatException)
                {
                    // ignore malformed references
                }
            }

            // Optionally try to detect target version through assembly path as a fallback (use case: reference assemblies)
            if (assemblyPath != null)
            {
                /*
                 * Detected path patterns (examples):
                 *
                 * - .NETFramework -> C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll
                 * - .NETCore      -> C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll
                 * - .NETStandard  -> C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll
                 */
                var pathMatch = Regex.Match(assemblyPath, PathPattern,
                                            RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
                string version;
                if (pathMatch.Success)
                {
                    var type = pathMatch.Groups["type"].Value;
                    version = pathMatch.Groups["version"].Value;
                    if (string.IsNullOrEmpty(version))
                    {
                        version = metadata.MetadataVersion;
                    }
                    if (string.IsNullOrEmpty(version))
                    {
                        version = "4.0";
                    }
                    version = version.TrimStart('v');

                    if (type == "Microsoft.NET" || type == ".NETFramework")
                    {
                        return($".NETFramework,Version=v{version.Substring(0, Math.Min(3, version.Length))}");
                    }
                    else if (type.IndexOf("netcore", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        return($".NETCoreApp,Version=v{version}");
                    }
                    else if (type.IndexOf("netstandard", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        return($".NETStandard,Version=v{version}");
                    }
                }
                else
                {
                    version = metadata.MetadataVersion;
                    if (string.IsNullOrEmpty(version))
                    {
                        version = "4.0";
                    }
                    version = version.TrimStart('v');
                    return($".NETFramework,Version=v{version.Substring(0, Math.Min(3, version.Length))}");
                }
            }

            return(string.Empty);
        }