Исключение AutoFac DependencyResolutionException при использовании гибридного кеша с RedisC#

Место общения программистов C#
Ответить
Anonymous
 Исключение AutoFac DependencyResolutionException при использовании гибридного кеша с Redis

Сообщение Anonymous »

Я столкнулся с ошибкой выполнения при использовании autofac в сочетании с гибридным кешем и Redis. Я надеюсь, что кто-нибудь сможет объяснить, почему возникает эта ошибка.
При использовании autofac для разрешения экземпляра HybridCache в сочетании с redis autofac выдает исключение DependencyResolutionException, которое DefaultHybridCache пытается создать другой экземпляр самого себя. Это происходит при попытке разрешить экземпляр HybridcCache.
Полная ошибка:

DependencyResolutionException: конструктор типа «Microsoft.Extensions.Caching.Hybrid.Internal.DefaultHybridCache» попытался создать другой экземпляр самого себя. Это не разрешено, поскольку служба настроена на разрешение только одного экземпляра за весь срок действия.

Это происходит, когда я регистрирую Redis с общим мультиплексором. Я не уверен, почему это важно, код воспроизведения см. ниже. При использовании системы DI по умолчанию в .NET ошибок нет.
Итак, короткий вопрос: является ли это ошибкой в ​​autofac (или библиотеке redis/hybridcache) или я неправильно использую библиотеки?
Минимальное воспроизведение выглядит следующим образом:
Добавление autofac в серверное приложение blazor, настроенное, как показано ниже, дает исключение при разрешении ГирбидКэш.
using Autofac.Extensions.DependencyInjection;
using BlazorAppAutofac.Components;
using BlazorAppAutofac.Services;
using StackExchange.Redis;

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();

builder.Services.AddHybridCache();

IConnectionMultiplexer connectionMultiplexer = ConnectionMultiplexer.Connect(new ConfigurationOptions
{
EndPoints = { $"localhost:6379" },
AbortOnConnectFail = false,
});
builder.Services.AddSingleton(connectionMultiplexer);
builder.Services.AddStackExchangeRedisCache(options =>
{
options.ConnectionMultiplexerFactory = () => Task.FromResult(connectionMultiplexer);
options.InstanceName = "BlazorAppAutofac";
});

builder.Services.AddTransient();

При использовании приведенного ниже кода для регистрации Redis (без добавления мультиплексора) исключение не возникает.
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("localhost:6379");
options.InstanceName = "BlazorAppAutofac";
});

В Home.razor
@inject IMessageService MessageService

В MessageService.cs
public class MessageService : IMessageService
{
private readonly HybridCache _cache;

public MessageService(HybridCache cache)
{
_cache = cache;
}
}

Я ожидал, что оба варианта регистрации будут работать, поскольку они также работают с внедрением зависимостей по умолчанию.
Интересно, что в коде StackExchangeRedis есть некоторый код, который пытается обойти эту проблему.
internal sealed class RedisCacheImpl : RedisCache
{
private readonly IServiceProvider _services;

internal override bool IsHybridCacheActive()
=> _services.GetService() is not null;

public RedisCacheImpl(IOptions optionsAccessor, ILogger logger, IServiceProvider services)
: base(optionsAccessor, logger)
{
_services = services; // important: do not check for HybridCache here due to dependency - creates a cycle
}

public RedisCacheImpl(IOptions optionsAccessor, IServiceProvider services)
: base(optionsAccessor)
{
_services = services; // important: do not check for HybridCache here due to dependency - creates a cycle
}
}

Трассировка стека:
DependencyResolutionException: The constructor of type 'Microsoft.Extensions.Caching.Hybrid.Internal.DefaultHybridCache' attempted to create another instance of itself. This is not permitted because the service is configured to only allowed a single instance per lifetime scope.
Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid id, Func creator)
Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid primaryId, Nullable qualifyingId, Func creator)
Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action next)
Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder+c__DisplayClass14_0.b__1(ResolveRequestContext context)
Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder+c__DisplayClass14_0.b__1(ResolveRequestContext context)
Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action next)
Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder+c__DisplayClass14_0.b__1(ResolveRequestContext context)
Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext context)
Autofac.Core.Resolving.ResolveOperation.InvokePipeline(ref ResolveRequest request, DefaultResolveRequestContext requestContext)
Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ref ResolveRequest request)
Autofac.Core.Resolving.ResolveOperation.Autofac.Core.Resolving.IResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ref ResolveRequest request)
Autofac.Core.Resolving.Pipeline.DefaultResolveRequestContext.ResolveComponent(ref ResolveRequest request)
Autofac.Core.Activators.Reflection.AutowiringParameter+c__DisplayClass0_0.b__0()
Autofac.Core.Activators.Reflection.BoundConstructor.Instantiate()
Autofac.Core.Activators.Reflection.ReflectionActivator+c__DisplayClass14_0.b__0(ResolveRequestContext context, Action next)
Autofac.Core.Resolving.Middleware.DelegateMiddleware.Execute(ResolveRequestContext context, Action next)
Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder+c__DisplayClass14_0.b__1(ResolveRequestContext context)
Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action next)
Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder+c__DisplayClass14_0.b__1(ResolveRequestContext context)
Autofac.Extensions.DependencyInjection.KeyedServiceMiddleware.Execute(ResolveRequestContext context, Action next)
Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder+c__DisplayClass14_0.b__1(ResolveRequestContext context)
Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action next)


Подробнее здесь: https://stackoverflow.com/questions/797 ... with-redis
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»