diff --git a/src/libraries/System.Data.Common/ref/System.Data.Common.cs b/src/libraries/System.Data.Common/ref/System.Data.Common.cs
index a4bc1f651f202b..ce7de38a7aefd2 100644
--- a/src/libraries/System.Data.Common/ref/System.Data.Common.cs
+++ b/src/libraries/System.Data.Common/ref/System.Data.Common.cs
@@ -2095,6 +2095,7 @@ protected virtual void OnStateChange(System.Data.StateChangeEventArgs stateChang
System.Data.IDbTransaction System.Data.IDbConnection.BeginTransaction(System.Data.IsolationLevel isolationLevel) { throw null; }
System.Data.IDbCommand System.Data.IDbConnection.CreateCommand() { throw null; }
}
+ [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)]
public partial class DbConnectionStringBuilder : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.ComponentModel.ICustomTypeDescriptor
{
public DbConnectionStringBuilder() { }
@@ -2130,6 +2131,7 @@ public virtual void Clear() { }
protected internal void ClearPropertyDescriptors() { }
public virtual bool ContainsKey(string keyword) { throw null; }
public virtual bool EquivalentTo(System.Data.Common.DbConnectionStringBuilder connectionStringBuilder) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered.")]
protected virtual void GetProperties(System.Collections.Hashtable propertyDescriptors) { }
public virtual bool Remove(string keyword) { throw null; }
public virtual bool ShouldSerialize(string keyword) { throw null; }
diff --git a/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml
index ffcb7d78381c4e..3e47be79791de4 100644
--- a/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml
+++ b/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml
@@ -103,59 +103,5 @@
member
M:System.Data.ProviderBase.SchemaMapping.SetupSchemaWithoutKeyInfo(System.Data.MissingMappingAction,System.Data.MissingSchemaAction,System.Boolean,System.Data.DataColumn,System.Object)
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.GetProperties(System.Collections.Hashtable)
-
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetAttributes
-
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetClassName
-
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetComponentName
-
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetConverter
-
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetDefaultEvent
-
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetDefaultProperty
-
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetEditor(System.Type)
-
-
- ILLink
- IL2026
- member
- M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetEvents
-
diff --git a/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs b/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs
index 3c3ac63548ef8a..027fe42f0b08ef 100644
--- a/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs
+++ b/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs
@@ -12,6 +12,7 @@
namespace System.Data.Common
{
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public class DbConnectionStringBuilder : IDictionary, ICustomTypeDescriptor
{
// keyword->value currently listed in the connection string
@@ -387,6 +388,7 @@ internal Attribute[] GetAttributesFromCollection(AttributeCollection collection)
return attributes;
}
+ [RequiresUnreferencedCode("PropertyDescriptor's PropertyType cannot be statically discovered.")]
private PropertyDescriptorCollection GetProperties()
{
PropertyDescriptorCollection? propertyDescriptors = _propertyDescriptors;
@@ -412,11 +414,16 @@ private PropertyDescriptorCollection GetProperties()
return propertyDescriptors;
}
+ [RequiresUnreferencedCode("PropertyDescriptor's PropertyType cannot be statically discovered.")]
protected virtual void GetProperties(Hashtable propertyDescriptors)
{
long logScopeId = DataCommonEventSource.Log.EnterScope(" {0}", ObjectID);
try
{
+ // Below call is necessary to tell the trimmer that it should mark derived types appropriately.
+ // We cannot use overload which takes type because the result might differ if derived class implements ICustomTypeDescriptor.
+ Type thisType = GetType();
+
// show all strongly typed properties (not already added)
// except ConnectionString iff BrowsableConnectionString
Attribute[]? attributes;
@@ -562,16 +569,28 @@ private PropertyDescriptorCollection GetProperties(Attribute[]? attributes)
return new PropertyDescriptorCollection(filteredPropertiesArray);
}
-// TODO: Enable after System.ComponentModel.TypeConverter is annotated
+ // TODO-NULLABLE: Enable after System.ComponentModel.TypeConverter is annotated
#nullable disable
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "The type of component is statically known. This class is marked with [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]")]
string ICustomTypeDescriptor.GetClassName()
{
+ // Below call is necessary to tell the trimmer that it should mark derived types appropriately.
+ // We cannot use overload which takes type because the result might differ if derived class implements ICustomTypeDescriptor.
+ Type thisType = GetType();
return TypeDescriptor.GetClassName(this, true);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "The type of component is statically known. This class is marked with [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]")]
string ICustomTypeDescriptor.GetComponentName()
{
+ // Below call is necessary to tell the trimmer that it should mark derived types appropriately.
+ // We cannot use overload which takes type because the result might differ if derived class implements ICustomTypeDescriptor.
+ Type thisType = GetType();
return TypeDescriptor.GetComponentName(this, true);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "The type of component is statically known. This class is marked with [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]")]
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
@@ -606,8 +625,13 @@ EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "The type of component is statically known. This class is marked with [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]")]
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
+ // Below call is necessary to tell the trimmer that it should mark derived types appropriately.
+ // We cannot use overload which takes type because the result might differ if derived class implements ICustomTypeDescriptor.
+ Type thisType = GetType();
return TypeDescriptor.GetEvents(this, true);
}
[RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")]
diff --git a/src/libraries/System.Data.Common/tests/TrimmingTests/DbConnectionStringBuilder.cs b/src/libraries/System.Data.Common/tests/TrimmingTests/DbConnectionStringBuilder.cs
new file mode 100644
index 00000000000000..78ac56e9f751a2
--- /dev/null
+++ b/src/libraries/System.Data.Common/tests/TrimmingTests/DbConnectionStringBuilder.cs
@@ -0,0 +1,159 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Data.Common;
+using System.ComponentModel;
+using System.Collections;
+
+namespace DbConnectionStringBuilderTrimmingTests
+{
+ class Program
+ {
+ static int Main(string[] args)
+ {
+ DbConnectionStringBuilder2 dcsb2 = new();
+ ICustomTypeDescriptor td = dcsb2;
+
+ if (td.GetClassName() != "DbConnectionStringBuilderTrimmingTests.DbConnectionStringBuilder2")
+ {
+ throw new Exception("Class name got trimmed");
+ }
+
+ if (td.GetComponentName() != "Test Component Name")
+ {
+ throw new Exception("Component name got trimmed");
+ }
+
+ bool foundAttr = false;
+
+ foreach (Attribute attr in td.GetAttributes())
+ {
+ if (attr.GetType().Name == "TestAttribute")
+ {
+ if (attr.ToString() != "Test Attribute Value")
+ {
+ throw new Exception("Test attribute value differs");
+ }
+
+ if (foundAttr)
+ {
+ throw new Exception("More than one attribute found");
+ }
+
+ foundAttr = true;
+ }
+ }
+
+ if (!foundAttr)
+ {
+ throw new Exception("Attribute not found");
+ }
+
+ bool foundEvent = false;
+ bool foundEventWithDisplayName = false;
+
+ foreach (EventDescriptor ev in td.GetEvents())
+ {
+ if (ev.DisplayName == "TestEvent")
+ {
+ if (foundEvent)
+ {
+ throw new Exception("More than one event TestEvent found.");
+ }
+
+ foundEvent = true;
+ }
+
+ if (ev.DisplayName == "Event With DisplayName")
+ {
+ if (foundEventWithDisplayName)
+ {
+ throw new Exception("More than one event with display name found.");
+ }
+
+ foundEventWithDisplayName = true;
+ }
+ }
+
+ if (!foundEvent)
+ {
+ throw new Exception("Event not found");
+ }
+
+ if (!foundEventWithDisplayName)
+ {
+ throw new Exception("Event with DisplayName not found");
+ }
+
+ bool propertyFound = false;
+ foreach (DictionaryEntry kv in dcsb2.GetProperties2())
+ {
+ PropertyDescriptor val = (PropertyDescriptor)kv.Value;
+ if (val.Name == "TestProperty")
+ {
+ if (propertyFound)
+ {
+ throw new Exception("More than one property TestProperty found.");
+ }
+
+ propertyFound = true;
+ }
+ }
+
+ if (!propertyFound)
+ {
+ throw new Exception("Property not found");
+ }
+
+ return 100;
+ }
+ }
+
+ [Test("Test Attribute Value")]
+ class DbConnectionStringBuilder2 : DbConnectionStringBuilder, IComponent
+ {
+#pragma warning disable CS0067 // The event is never used
+ public event EventHandler Disposed;
+ public event Action TestEvent;
+ [DisplayName("Event With DisplayName")]
+ public event Action TestEvent2;
+#pragma warning restore CS0067
+
+ public string TestProperty { get; set; }
+ public ISite Site { get => new TestSite(); set => throw new NotImplementedException(); }
+ public void Dispose() { }
+
+ public Hashtable GetProperties2()
+ {
+ Hashtable propertyDescriptors = new Hashtable();
+ GetProperties(propertyDescriptors);
+ return propertyDescriptors;
+ }
+ }
+
+ class TestSite : INestedSite
+ {
+ public string FullName => null;
+ public IComponent Component => throw new NotImplementedException();
+ public IContainer Container => throw new NotImplementedException();
+ public bool DesignMode => throw new NotImplementedException();
+ public string Name { get => "Test Component Name"; set => throw new NotImplementedException(); }
+ public object GetService(Type serviceType) => null;
+ }
+
+ class TestAttribute : Attribute
+ {
+ public string Test { get; private set; }
+
+ public TestAttribute(string test)
+ {
+ Test = test;
+ }
+
+ public override string ToString()
+ {
+ return Test;
+ }
+ }
+}
diff --git a/src/libraries/System.Data.Common/tests/TrimmingTests/System.Data.Common.TrimmingTests.proj b/src/libraries/System.Data.Common/tests/TrimmingTests/System.Data.Common.TrimmingTests.proj
index da4a46f2ae141a..7254c33fc9c7ba 100644
--- a/src/libraries/System.Data.Common/tests/TrimmingTests/System.Data.Common.TrimmingTests.proj
+++ b/src/libraries/System.Data.Common/tests/TrimmingTests/System.Data.Common.TrimmingTests.proj
@@ -1,5 +1,10 @@
+
+
+
+
+