dotnet / dotnet/runtime

DbConnectionStringBuilder annotations force invalid suppressions on library authors

Open
#121,718 3 comments 0 reactions 0 assignees View on GitHub
area-System.ComponentModel
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

DbConnectionStringBuilder has `DynamicallyAccessedMembers` on the type:
https://github.com/dotnet/runtime/blob/ea694d84df646ef212a74e83c8bfafa053d46606/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs#L18-L24

which says that it's trim-compatible to reflect over the specified members of `DbConnectionStringBuilder` or derived types. But at the same item, several members are marked as `RequiresUnreferencedCode`:
https://github.com/dotnet/runtime/blob/ea694d84df646ef212a74e83c8bfafa053d46606/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs#L400-L404

The suppression on `GetProperties` is invalid because it allows:

```csharp
new DbConnectionStringBuilder().GetType().GetMethods(...)
```

which is reflecting over RUC methods but doesn't produce trim warnings. The annotations also lead to unactionable trim warnings:

```csharp
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Collections;
using System.ComponentModel.DataAnnotations;
using System.Data.Common;
using System.Diagnostics.CodeAnalysis;

var db = new MyStringBuilder();

new ServiceCollection()
.Configure(settings =>
{
settings.Option = true;
})
.AddSingleton, MyValidator>()
.AddSingleton()
.BuildServiceProvider();

public class MySettings
{
[Required]
public bool Option { get; set; }
}

class SettingsHelper
{
private readonly IOptions _options;

public SettingsHelper(IOptions options)
{
_options = options;
}
}

[OptionsValidator]
public partial class MyValidator : IValidateOptions
{
}

class MyStringBuilder : DbConnectionStringBuilder
{
[RequiresUnreferencedCode("GetProperties")]
protected override void GetProperties(Hashtable propertyDescriptors)
{
base.GetProperties(propertyDescriptors);
}
}
```

This produces a trim warning from `MyStringBuilder.GetProperties`, but only when both `MyStringBuilder` and the options validation logic are referenced from the app (because the options validation logic internally uses `ICustomTypeDescriptor.GetProperties`):

```
warning IL2112: 'DynamicallyAccessedMembersAttribute' on 'MyStringBuilder' or one of its base types references 'MyStringBuilder.GetProperties(Hashtable)' which requires unreferenced code. GetProperties.
```

I'm opening this issue because I have seen this cause confusion in various places, and I think it's worth writing down our recommendations. Given the way we have annotated `DbConnectiontStringBuilder`, I think the current recommendation is for all derived types to suppress the warnings from the derived members (so add `UnconditionalSuppressMessage("IL2112", ...)` to the `GetProperties` override in this example). This is not ideal because it forces the library author to add an invalid suppression.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.