Browse Source
Introduce AddAbpOptions to prevent options deadlocks
Related to #24247
pull/24260/head
maliming
2 months ago
No known key found for this signature in database
GPG Key ID: A646B9CB645ECEA4
10 changed files with
65 additions and
9 deletions
framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs
framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionOptionsExtensions.cs
framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpUnnamedOptionsManager.cs
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs
framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs
@ -13,7 +13,7 @@ public class AbpAspNetCoreMvcNewtonsoftModule : AbpModule
{
context . Services . AddMvcCore ( ) . AddNewtonsoftJson ( ) ;
context . Services . AddOptions < MvcNewtonsoftJsonOptions > ( )
context . Services . AddAbp Options < MvcNewtonsoftJsonOptions > ( )
. Configure < IServiceProvider > ( ( options , rootServiceProvider ) = >
{
options . SerializerSettings . ContractResolver =
@ -165,7 +165,7 @@ public class AbpAspNetCoreMvcModule : AbpModule
context . Services . AddSingleton < ValidationAttributeAdapterProvider > ( ) ;
context . Services . TryAddEnumerable ( ServiceDescriptor . Transient < IActionDescriptorProvider , AbpMvcActionDescriptorProvider > ( ) ) ;
context . Services . AddOptions < MvcOptions > ( )
context . Services . AddAbp Options < MvcOptions > ( )
. Configure < IServiceProvider > ( ( mvcOptions , serviceProvider ) = >
{
mvcOptions . AddAbp ( context . Services ) ;
@ -13,7 +13,7 @@ public static class MvcCoreBuilderExtensions
{
public static IMvcCoreBuilder AddAbpJson ( this IMvcCoreBuilder builder )
{
builder . Services . AddOptions < JsonOptions > ( )
builder . Services . AddAbp Options < JsonOptions > ( )
. Configure < IServiceProvider > ( ( options , rootServiceProvider ) = >
{
options . JsonSerializerOptions . ReadCommentHandling = JsonCommentHandling . Skip ;
@ -0,0 +1,22 @@
using Microsoft.Extensions.DependencyInjection.Extensions ;
using Microsoft.Extensions.Options ;
using Volo.Abp.Options ;
namespace Microsoft.Extensions.DependencyInjection ;
public static class ServiceCollectionOptionsExtensions
{
/// <summary>
/// You should only use this method to register options if you need to continue using the ServiceProvider to get other options in your Options configuration method.
/// Otherwise, please use the default AddOptions method for better performance.
/// </summary>
/// <param name="services"></param>
/// <typeparam name="TOptions"></typeparam>
/// <returns></returns>
public static OptionsBuilder < TOptions > AddAbpOptions < TOptions > ( this IServiceCollection services )
where TOptions : class
{
services . TryAddSingleton < IOptions < TOptions > , AbpUnnamedOptionsManager < TOptions > > ( ) ;
return services . AddOptions < TOptions > ( ) ;
}
}
@ -0,0 +1,34 @@
using Microsoft.Extensions.Options ;
namespace Volo.Abp.Options ;
/// <summary>
/// This Options manager is similar to Microsoft UnnamedOptionsManager but without the locking mechanism.
/// Prevent deadlocks when accessing options in multiple threads.
/// </summary>
/// <typeparam name="TOptions"></typeparam>
public class AbpUnnamedOptionsManager < TOptions > : IOptions < TOptions >
where TOptions : class
{
private readonly IOptionsFactory < TOptions > _f actory ;
private volatile TOptions ? _ value ;
public AbpUnnamedOptionsManager ( IOptionsFactory < TOptions > factory )
{
_f actory = factory ;
}
public TOptions Value
{
get
{
if ( _ value is TOptions value )
{
return value ;
}
_ value = _f actory . Create ( Microsoft . Extensions . Options . Options . DefaultName ) ;
return _ value ;
}
}
}
@ -10,7 +10,7 @@ public class AbpJsonNewtonsoftModule : AbpModule
{
public override void ConfigureServices ( ServiceConfigurationContext context )
{
context . Services . AddOptions < AbpNewtonsoftJsonSerializerOptions > ( )
context . Services . AddAbp Options < AbpNewtonsoftJsonSerializerOptions > ( )
. Configure < IServiceProvider > ( ( options , rootServiceProvider ) = >
{
options . JsonSerializerSettings . ContractResolver = new AbpCamelCasePropertyNamesContractResolver (
@ -15,7 +15,7 @@ public class AbpJsonSystemTextJsonModule : AbpModule
{
public override void ConfigureServices ( ServiceConfigurationContext context )
{
context . Services . AddOptions < AbpSystemTextJsonSerializerOptions > ( )
context . Services . AddAbp Options < AbpSystemTextJsonSerializerOptions > ( )
. Configure < IServiceProvider > ( ( options , rootServiceProvider ) = >
{
// If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters.
@ -19,7 +19,7 @@ public class AbpJsonSystemTextJsonTestModule : AbpModule
{
public override void ConfigureServices ( ServiceConfigurationContext context )
{
context . Services . AddOptions < AbpSystemTextJsonSerializerOptions > ( )
context . Services . AddAbp Options < AbpSystemTextJsonSerializerOptions > ( )
. Configure < IServiceProvider > ( ( options , rootServiceProvider ) = >
{
if ( options . JsonSerializerOptions . TypeInfoResolver ! = null )
@ -43,7 +43,7 @@ public class AbpJsonNewtonsoftTestModule : AbpModule
{
public override void ConfigureServices ( ServiceConfigurationContext context )
{
context . Services . AddOptions < AbpNewtonsoftJsonSerializerOptions > ( )
context . Services . AddAbp Options < AbpNewtonsoftJsonSerializerOptions > ( )
. Configure < IServiceProvider > ( ( options , rootServiceProvider ) = >
{
options . JsonSerializerSettings . ContractResolver = new AbpCamelCasePropertyNamesContractResolver (
@ -34,7 +34,7 @@ public class AbpMemoryDbTestModule : AbpModule
options . AddRepository < City , CityRepository > ( ) ;
} ) ;
context . Services . AddOptions < Utf8JsonMemoryDbSerializerOptions > ( )
context . Services . AddAbp Options < Utf8JsonMemoryDbSerializerOptions > ( )
. Configure < IServiceProvider > ( ( options , rootServiceProvider ) = >
{
options . JsonSerializerOptions . Converters . Add ( new EntityJsonConverter < EntityWithIntPk , int > ( ) ) ;
@ -47,7 +47,7 @@ public class AbpIdentityAspNetCoreModule : AbpModule
public override void PostConfigureServices ( ServiceConfigurationContext context )
{
context . Services . AddOptions < SecurityStampValidatorOptions > ( )
context . Services . AddAbp Options < SecurityStampValidatorOptions > ( )
. Configure < IServiceProvider > ( ( securityStampValidatorOptions , serviceProvider ) = >
{
var abpRefreshingPrincipalOptions = serviceProvider . GetRequiredService < IOptions < AbpRefreshingPrincipalOptions > > ( ) . Value ;