Не удается разрешить зависимость IMemoryCache

#.net-core #autofac

#c# #.net-ядро #autofac

Вопрос:

У меня есть приложение-служба, размещенное на net.core 3.1. В этом приложении autofac используется в качестве контейнера DI в дополнение к стандартному контейнеру. Я пытаюсь добавить и использовать IMemoryCache следующим образом:

  1. В Program.cs
 Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration(...)
    ...etc
    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .ConfigureServices((hostContext, services) =>
    {
        // Register configuration
        services.AddMemoryCache();
        // some another services
    }
    .ConfigureContainer<ContainerBuilder>(ConfigureContainer)
    .UseConsoleLifetime();
  
  1. ConfigureContainer — это метод, в котором некоторые типы регистрируются с помощью autofac.
  2. В моем сервисе я добавляю зависимость кеша памяти следующим образом:
     public class MyService: IMyService
    {
        private readonly IMemoryCache _memoryCache;
        
        public MyService(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }
    }
  

Но я получаю это исключение при запуске приложения:

 Autofac.Core.DependencyResolutionException: An exception was thrown while activating λ:Microsoft.Extensions.Hosting.IHostedService[] -> MyNamespace.WorkerService -> MyNamespace.MyAnotherService -> MyNamespace.SomeAnotherService -> MyNamespace.MyService -> Microsoft.Extensions.Caching.Memory.MemoryCache.
 ---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor(Microsoft.Extensions.Options.IOptions`1[Microsoft.Extensions.Caching.Memory.MemoryCacheOptions])' on type 'MemoryCache'.
 ---> System.TypeLoadException: Method 'get_Size' in type 'Microsoft.Extensions.Caching.Memory.CacheEntry' from assembly 'Microsoft.Extensions.Caching.Memory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' does not have an implementation.
   at Microsoft.Extensions.Caching.Memory.MemoryCache..ctor(IOptions`1 optionsAccessor)
   at lambda_method(Closure , Object[] )
   at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
   --- End of inner exception stack trace ---
   at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.CreateInstance(IEnumerable`1 parameters)
   --- End of inner exception stack trace ---
   at Autofac.Core.Resolving.InstanceLookup.CreateInstance(IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Execute()
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
   at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(ResolveRequest request)
   at Autofac.Core.Resolving.ResolveOperation.Execute(ResolveRequest request)
   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(ResolveRequest request)
   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Objectamp; instance)
   at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType)
   at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at MyNamespace.Program.Main(String[] args)
  

Я попытался зарегистрировать все необходимые для кэширования службы вручную, используя autofac в ConfigureContainer вместо использования .AddMemoryCache() как показано ниже (копировать вставить из .AddMemoryCache() тела):

 builder.RegisterType(typeof(OptionsManager<>)).As(typeof(IOptions<>)).SingleInstance();
builder.RegisterType(typeof(OptionsManager<>)).As(typeof(IOptionsSnapshot<>));
builder.RegisterType(typeof(OptionsMonitor<>)).As(typeof(IOptionsMonitor<>)).SingleInstance();
builder.RegisterType(typeof(OptionsMonitor<>)).As(typeof(IOptionsFactory<>)).SingleInstance();
builder.RegisterType(typeof(OptionsFactory<>)).As(typeof(IOptionsMonitorCache<>)).SingleInstance();
builder.RegisterType<MemoryCache>().As<IMemoryCache>().SingleInstance();
  

но в этом случае я получаю другое исключение:

 System.ArgumentException: The type 'Microsoft.Extensions.Options.OptionsManager`1[TOptions]' is not assignable to service 'Microsoft.Extensions.Options.IOptions`1'.
   at Autofac.Builder.RegistrationBuilder.CreateRegistration(Guid id, RegistrationData data, IInstanceActivator activator, Service[] services, IComponentRegistration target, Boolean isAdapterForIndividualComponent)
   at Autofac.Builder.RegistrationBuilder.CreateRegistration[TLimit,TActivatorData,TSingleRegistrationStyle](IRegistrationBuilder`3 builder)
   at Autofac.Builder.RegistrationBuilder.RegisterSingleComponent[TLimit,TActivatorData,TSingleRegistrationStyle](IComponentRegistryBuilder cr, IRegistrationBuilder`3 builder)
   at Autofac.RegistrationExtensions.<>c__DisplayClass3_0.<RegisterType>b__0(IComponentRegistryBuilder cr)
   at Autofac.ContainerBuilder.Build(IComponentRegistryBuilder componentRegistry, Boolean excludeDefaultModules)
   at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)
   at Autofac.Extensions.DependencyInjection.AutofacServiceProviderFactory.CreateServiceProvider(ContainerBuilder containerBuilder)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
  

Есть предложения?

Комментарии:

1. Не могли бы вы предоставить полный код Program.cs ?

2. Я не могу воспроизвести, но во втором случае, когда вы добавляете зависимости вручную, я думаю, вы можете добавить только последнюю строку.

Ответ №1:

Я нашел свою ошибку. Благодаря Сергею, я проверил свой Program.cs и обнаружил, что я использую .AddMemoryCache() расширение одновременно с регистрацией IMemoryCache в ConfigureContainer. Необходимо использовать только метод расширения, ручная регистрация IMemoryCache не требуется.