Skip to content

Commit cf3d2b8

Browse files
authored
[Extensions] Add AOT compatibility attributes to Microsoft.Extensions.Azure (#41936)
* [Extensions] Add AOT compatibility attributes Annotate the Microsoft.Extensions.Azure library for trimming/AOT compatibility. Also add a few suppressions to Azure.Identity's EventSource that showed up when I was using Microsoft.Extensions.Azure in a real-world app. * Add expected AOT warnings for DiagnosticSource.Write These warnings went away with dotnet/runtime#76109, which was backported to .NET 7.0.3, but the CI build machines are still using an older 7.0.x, which don't have these warnings fixed. Adding expected warnings entries for them until we take a new .NET version in CI. * Fix CI errors. * Add CheckAOTCompat to Azure.Identity * Fix up Identity expected aot warnings for CI.
1 parent 89d810e commit cf3d2b8

18 files changed

+143
-25
lines changed

sdk/core/Azure.Core/api/Azure.Core.net6.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,7 @@ public partial interface IAzureClientFactoryBuilder
803803
}
804804
public partial interface IAzureClientFactoryBuilderWithConfiguration<in TConfiguration> : Azure.Core.Extensions.IAzureClientFactoryBuilder
805805
{
806+
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
806807
Azure.Core.Extensions.IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<TClient, TOptions>(TConfiguration configuration) where TOptions : class;
807808
}
808809
public partial interface IAzureClientFactoryBuilderWithCredential

sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Diagnostics.CodeAnalysis;
56

67
namespace Azure.Core.Extensions
78
{
@@ -17,6 +18,6 @@ public interface IAzureClientFactoryBuilder
1718
/// <typeparam name="TOptions">The client options type used the client.</typeparam>
1819
/// <param name="clientFactory">The factory, that given the instance of options, returns a client instance.</param>
1920
/// <returns><see cref="IAzureClientBuilder{TClient,TOptions}"/> that allows customizing the client registration.</returns>
20-
IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<TClient, TOptions>(Func<TOptions, TClient> clientFactory) where TOptions : class;
21+
IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(Func<TOptions, TClient> clientFactory) where TOptions : class;
2122
}
2223
}

sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilderWithConfiguration.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using System.Diagnostics.CodeAnalysis;
5+
46
namespace Azure.Core.Extensions
57
{
68
/// <summary>
@@ -15,6 +17,8 @@ public interface IAzureClientFactoryBuilderWithConfiguration<in TConfiguration>
1517
/// <typeparam name="TOptions">The client options type used the client.</typeparam>
1618
/// <param name="configuration">Instance of <typeparamref name="TConfiguration"/> to use.</param>
1719
/// <returns><see cref="IAzureClientBuilder{TClient,TOptions}"/> that allows customizing the client registration.</returns>
18-
IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<TClient, TOptions>(TConfiguration configuration) where TOptions : class;
20+
[RequiresUnreferencedCode("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
21+
[RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
22+
IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(TConfiguration configuration) where TOptions : class;
1923
}
2024
}

sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilderWithCredential.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Diagnostics.CodeAnalysis;
56

67
namespace Azure.Core.Extensions
78
{
@@ -18,6 +19,6 @@ public interface IAzureClientFactoryBuilderWithCredential
1819
/// <param name="clientFactory">The factory, that given the instance of options and credential, returns a client instance.</param>
1920
/// <param name="requiresCredential">Specifies whether the credential is optional (client supports anonymous authentication).</param>
2021
/// <returns><see cref="IAzureClientBuilder{TClient,TOptions}"/> that allows customizing the client registration.</returns>
21-
IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<TClient, TOptions>(Func<TOptions, TokenCredential, TClient> clientFactory, bool requiresCredential = true) where TOptions : class;
22+
IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(Func<TOptions, TokenCredential, TClient> clientFactory, bool requiresCredential = true) where TOptions : class;
2223
}
2324
}

sdk/extensions/Microsoft.Extensions.Azure/src/AzureClientBuilderExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.Extensions.DependencyInjection;
88
using Microsoft.Extensions.Options;
99
using System;
10+
using System.Diagnostics.CodeAnalysis;
1011

1112
namespace Microsoft.Extensions.Azure
1213
{
@@ -78,6 +79,8 @@ public static IAzureClientBuilder<TClient, TOptions> ConfigureOptions<TClient, T
7879
/// <param name="builder">The client builder instance.</param>
7980
/// <param name="configuration">The configuration instance to use.</param>
8081
/// <returns>The client builder instance.</returns>
82+
[RequiresUnreferencedCode("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
83+
[RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
8184
public static IAzureClientBuilder<TClient, TOptions> ConfigureOptions<TClient, TOptions>(this IAzureClientBuilder<TClient, TOptions> builder, IConfiguration configuration) where TOptions : class
8285
{
8386
return builder.ConfigureOptions(options => configuration.Bind(options));

sdk/extensions/Microsoft.Extensions.Azure/src/AzureClientFactoryBuilder.cs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Diagnostics.CodeAnalysis;
56
using Azure.Core;
67
using Azure.Core.Extensions;
78
using Microsoft.Extensions.Configuration;
@@ -25,12 +26,16 @@ internal AzureClientFactoryBuilder(IServiceCollection serviceCollection)
2526
_serviceCollection = serviceCollection;
2627
}
2728

28-
IAzureClientBuilder<TClient, TOptions> IAzureClientFactoryBuilder.RegisterClientFactory<TClient, TOptions>(Func<TOptions, TClient> clientFactory)
29+
IAzureClientBuilder<TClient, TOptions> IAzureClientFactoryBuilder.RegisterClientFactory<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(
30+
Func<TOptions, TClient> clientFactory)
2931
{
3032
return ((IAzureClientFactoryBuilderWithCredential)this).RegisterClientFactory<TClient, TOptions>((options, _) => clientFactory(options));
3133
}
3234

33-
IAzureClientBuilder<TClient, TOptions> IAzureClientFactoryBuilderWithConfiguration<IConfiguration>.RegisterClientFactory<TClient, TOptions>(IConfiguration configuration)
35+
[RequiresUnreferencedCode("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
36+
[RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
37+
IAzureClientBuilder<TClient, TOptions> IAzureClientFactoryBuilderWithConfiguration<IConfiguration>.RegisterClientFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(
38+
IConfiguration configuration)
3439
{
3540
var credentialsFromConfig = ClientFactory.CreateCredential(configuration);
3641
var clientBuilder =((IAzureClientFactoryBuilderWithCredential)this).RegisterClientFactory<TClient, TOptions>(
@@ -73,6 +78,8 @@ public AzureClientFactoryBuilder ConfigureDefaults(Action<ClientOptions, IServic
7378
/// </summary>
7479
/// <param name="configuration">The configuration instance.</param>
7580
/// <returns>This instance.</returns>
81+
[RequiresUnreferencedCode("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
82+
[RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
7683
public AzureClientFactoryBuilder ConfigureDefaults(IConfiguration configuration)
7784
{
7885
ConfigureDefaults(configuration.Bind);
@@ -87,7 +94,8 @@ public AzureClientFactoryBuilder ConfigureDefaults(IConfiguration configuration)
8794
return this;
8895
}
8996

90-
IAzureClientBuilder<TClient, TOptions> IAzureClientFactoryBuilderWithCredential.RegisterClientFactory<TClient, TOptions>(Func<TOptions, TokenCredential, TClient> clientFactory, bool requiresCredential)
97+
IAzureClientBuilder<TClient, TOptions> IAzureClientFactoryBuilderWithCredential.RegisterClientFactory<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(
98+
Func<TOptions, TokenCredential, TClient> clientFactory, bool requiresCredential)
9199
{
92100
return RegisterClientFactory<TClient, TOptions>((options, credential, _) => clientFactory(options, credential), requiresCredential);
93101
}
@@ -119,7 +127,9 @@ public AzureClientFactoryBuilder UseCredential(Func<IServiceProvider, TokenCrede
119127
/// <typeparam name="TClient">The type of the client.</typeparam>
120128
/// <typeparam name="TOptions">The type of the client options.</typeparam>
121129
/// <returns>The <see cref="IAzureClientBuilder{TClient, TOptions}"/> to allow client configuration.</returns>
122-
public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, TOptions>(Func<TOptions, TClient> factory) where TOptions : class
130+
public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(
131+
Func<TOptions, TClient> factory)
132+
where TOptions : class
123133
{
124134
return RegisterClientFactory<TClient, TOptions>((options, _, _) => factory(options), false);
125135
}
@@ -130,7 +140,9 @@ public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, TOptions>(Func<
130140
/// <typeparam name="TClient">The type of the client.</typeparam>
131141
/// <typeparam name="TOptions">The type of the client options.</typeparam>
132142
/// <returns>The <see cref="IAzureClientBuilder{TClient, TOptions}"/> to allow client configuration.</returns>
133-
public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, TOptions>(Func<TOptions, TokenCredential, TClient> factory) where TOptions : class
143+
public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(
144+
Func<TOptions, TokenCredential, TClient> factory)
145+
where TOptions : class
134146
{
135147
return RegisterClientFactory<TClient, TOptions>((options, credential, _) => factory(options, credential), true);
136148
}
@@ -142,7 +154,9 @@ public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, TOptions>(Func<
142154
/// <typeparam name="TClient">The type of the client.</typeparam>
143155
/// <typeparam name="TOptions">The type of the client options.</typeparam>
144156
/// <returns>The <see cref="IAzureClientBuilder{TClient, TOptions}"/> to allow client configuration.</returns>
145-
public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, TOptions>(Func<TOptions, IServiceProvider, TClient> factory) where TOptions : class
157+
public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(
158+
Func<TOptions, IServiceProvider, TClient> factory)
159+
where TOptions : class
146160
{
147161
return RegisterClientFactory<TClient, TOptions>((options, _, provider) => factory(options, provider), true);
148162
}
@@ -154,12 +168,17 @@ public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, TOptions>(Func<
154168
/// <typeparam name="TClient">The type of the client.</typeparam>
155169
/// <typeparam name="TOptions">The type of the client options.</typeparam>
156170
/// <returns>The <see cref="IAzureClientBuilder{TClient, TOptions}"/> to allow client configuration.</returns>
157-
public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, TOptions>(Func<TOptions, TokenCredential, IServiceProvider, TClient> factory) where TOptions : class
171+
public IAzureClientBuilder<TClient, TOptions> AddClient<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(
172+
Func<TOptions, TokenCredential, IServiceProvider, TClient> factory)
173+
where TOptions : class
158174
{
159175
return RegisterClientFactory<TClient, TOptions>((options, credential, provider) => factory(options, credential, provider), true);
160176
}
161177

162-
private IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<TClient, TOptions>(Func<TOptions, TokenCredential, IServiceProvider, TClient> clientFactory, bool requiresCredential) where TOptions : class
178+
private IAzureClientBuilder<TClient, TOptions> RegisterClientFactory<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>(
179+
Func<TOptions, TokenCredential, IServiceProvider, TClient> clientFactory,
180+
bool requiresCredential)
181+
where TOptions : class
163182
{
164183
var clientRegistration = new ClientRegistration<TClient>(DefaultClientName, requiresCredential, (provider, options, credential) => clientFactory((TOptions) options, credential, provider));
165184
_serviceCollection.AddSingleton(clientRegistration);

sdk/extensions/Microsoft.Extensions.Azure/src/AzureComponentFactory.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Diagnostics.CodeAnalysis;
56
using Azure.Core;
67
using Microsoft.Extensions.Configuration;
78

@@ -24,7 +25,12 @@ public abstract class AzureComponentFactory
2425
/// <param name="serviceVersion">The value of ServiceVersion enum to use, null to use the default.</param>
2526
/// <param name="configuration">The <see cref="IConfiguration"/> instance to apply to options.</param>
2627
/// <returns>A new instance of <paramref name="optionsType"/>.</returns>
27-
public abstract object CreateClientOptions(Type optionsType, object serviceVersion, IConfiguration configuration);
28+
[RequiresUnreferencedCode("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
29+
[RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
30+
public abstract object CreateClientOptions(
31+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type optionsType,
32+
object serviceVersion,
33+
IConfiguration configuration);
2834

2935
/// <summary>
3036
/// Creates a new client instance using the provided configuration to map constructor parameters from.
@@ -35,6 +41,11 @@ public abstract class AzureComponentFactory
3541
/// <param name="credential">The <see cref="TokenCredential"/> object to use if required by constructor, if null no .</param>
3642
/// <param name="clientOptions">The client </param>
3743
/// <returns></returns>
38-
public abstract object CreateClient(Type clientType, IConfiguration configuration, TokenCredential credential, object clientOptions);
44+
[RequiresUnreferencedCode("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
45+
public abstract object CreateClient(
46+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type clientType,
47+
IConfiguration configuration,
48+
TokenCredential credential,
49+
object clientOptions);
3950
}
4051
}

sdk/extensions/Microsoft.Extensions.Azure/src/Internal/AzureClientFactory.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Diagnostics.CodeAnalysis;
67
using System.Threading.Tasks;
78
using Microsoft.Extensions.Options;
89

910
namespace Microsoft.Extensions.Azure
1011
{
11-
internal class AzureClientFactory<TClient, TOptions>: IAzureClientFactory<TClient>, IDisposable, IAsyncDisposable
12+
internal class AzureClientFactory<TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TOptions>
13+
: IAzureClientFactory<TClient>, IDisposable, IAsyncDisposable
1214
{
1315
private readonly Dictionary<string, ClientRegistration<TClient>> _clientRegistrations;
1416

sdk/extensions/Microsoft.Extensions.Azure/src/Internal/AzureComponentFactoryImpl.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Diagnostics.CodeAnalysis;
56
using Azure.Core;
67
using Microsoft.Extensions.Configuration;
78
using Microsoft.Extensions.Options;
@@ -25,7 +26,12 @@ public override TokenCredential CreateTokenCredential(IConfiguration configurati
2526
return ClientFactory.CreateCredential(configuration) ?? _globalOptions.CurrentValue.CredentialFactory(_serviceProvider);
2627
}
2728

28-
public override object CreateClientOptions(Type optionsType, object serviceVersion, IConfiguration configuration)
29+
[RequiresUnreferencedCode("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
30+
[RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
31+
public override object CreateClientOptions(
32+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type optionsType,
33+
object serviceVersion,
34+
IConfiguration configuration)
2935
{
3036
if (optionsType == null) throw new ArgumentNullException(nameof(optionsType));
3137
var options = ClientFactory.CreateClientOptions(serviceVersion, optionsType);
@@ -41,7 +47,12 @@ public override object CreateClientOptions(Type optionsType, object serviceVersi
4147
return options;
4248
}
4349

44-
public override object CreateClient(Type clientType, IConfiguration configuration, TokenCredential credential, object clientOptions)
50+
[RequiresUnreferencedCode("Binding strongly typed objects to configuration values is not supported with trimming. Use the Configuration Binder Source Generator (EnableConfigurationBindingGenerator=true) instead.")]
51+
public override object CreateClient(
52+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type clientType,
53+
IConfiguration configuration,
54+
TokenCredential credential,
55+
object clientOptions)
4556
{
4657
if (clientType == null) throw new ArgumentNullException(nameof(clientType));
4758
if (configuration == null) throw new ArgumentNullException(nameof(configuration));

0 commit comments

Comments
 (0)