Skip to content

Allow DefaultValueAttribute with primitives when System.ComponentModel.DefaultValueAttribute.IsSupported disabled #103542

@OwnageIsMagic

Description

@OwnageIsMagic

Description

DefaultValueAttribute.Value throws on access (due to #100416) when System.ComponentModel.DefaultValueAttribute.IsSupported switch is false and it breaks XmlSerializer and other serializers/reflection. But it's very common to use not (Type, string) overload, but 1 arg primitive which do not use TypeDescriptor API family.

Reproduction Steps

using System.ComponentModel;
using System.Xml.Serialization;

// _ = typeof(C).GetProperty("i")!.GetCustomAttribute<DefaultValueAttribute>()!.Value;
XmlSerializer serializer = new(typeof(C));

public class C { [DefaultValue(5)] public int i {get; set;} }
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <RuntimeHostConfigurationOption
      Include="System.ComponentModel.DefaultValueAttribute.IsSupported"
      Value="false" Trim="true" />
  </ItemGroup>

</Project>

Expected behavior

No exception, use constructor arg as is.

Actual behavior

Unhandled exception. System.InvalidOperationException: There was an error reflecting type 'C'.
 ---> System.ArgumentException: Runtime instantiation of this attribute is not allowed.
   at System.ComponentModel.DefaultValueAttribute.get_Value()
   at System.Xml.Serialization.XmlAttributes..ctor(ICustomAttributeProvider provider)
   at System.Xml.Serialization.XmlReflectionImporter.GetAttributes(MemberInfo memberInfo)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
   at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
   at Program.<Main>$(String[] args) in C:\Source\ttt\Program.cs:line 4

Workaround

set _value to some sentinel if TypeDescriptor is required and throw only in this case.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions