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
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions