- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.2k
Description
Description
Copied from dotnet/winforms#11314
Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.
TypeDescriptor accesses these methods here
Suggested fix from @ericstj
The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)
That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)
Search pattern for ShouldSerialize
Search pattern for Reset
Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the  public, serializable property, or method is actually called directly.  For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.
Reproduction Steps
This works on 4.8.1 but doesn't on net6
using System;
using System.ComponentModel;
using System.Data;
namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            DataColumn dataColumn1 = new DataColumn
            {
                ColumnName = "dataColumn1",
                DataType = typeof(DateTime)
            };
            var properties = TypeDescriptor.GetProperties(dataColumn1);
            var property = properties[nameof(DataColumn.DefaultValue)];
            if (property != null)
            {
                bool shouldSerialize = property.ShouldSerializeValue(dataColumn1);
                Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");
                dataColumn1.DefaultValue = DateTime.MinValue;
                shouldSerialize = property.ShouldSerializeValue(dataColumn1);
                Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");
                // Reset method is not available
                property.ResetValue(dataColumn1);
                Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");
            }
            property = properties[nameof(DataColumn.Caption)];
            if (property != null)
            {
                bool shouldSerialize = property.ShouldSerializeValue(dataColumn1);
                Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");
                dataColumn1.Caption = "Caption";
                shouldSerialize = property.ShouldSerializeValue(dataColumn1);
                Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");
                // Reset method is available
                property.ResetValue(dataColumn1);
                Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");
            }
            property = properties[nameof(DataColumn.Namespace)];
            if (property != null)
            {
                bool shouldSerialize = property.ShouldSerializeValue(dataColumn1);
                Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");
                dataColumn1.Namespace = "Namespace";
                shouldSerialize = property.ShouldSerializeValue(dataColumn1);
                Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");
                // Reset method is available
                property.ResetValue(dataColumn1);
                Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");
            }
            _ = Console.ReadLine();
        }
    }
}Expected behavior
ShouldSerialize, Reset methods are present in the assembly
Actual behavior
ShouldSerialize, Reset methods are trimmed
Regression?
The end scenario regressed between the InProc and OOP designers.
Known Workarounds
none
Configuration
WIndows
Other information
Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.