簡體   English   中英

激活 Autofac .NET Core Web API 時檢測到循環組件依賴項

[英]Circular component dependency detected while activating Autofac .NET Core Web API

我有 IAfterSaleService 接口和 AfterSaleService 類的問題,我對這些 cs 文件使用了 autofac IoC。 然而,雖然我所做的構造函數注入適用於某些接口,但售后服務不適用於某些構造函數注入。 例如,雖然 IAfterService 在 AfterServiceController 的構造函數中起作用,但在同一目錄下的其他服務(如 OrderService.cs...)的構造函數中不起作用

我收到以下異常響應

Autofac.Core.DependencyResolutionException:在激活 Retail.Business.Concretes.AfterSaleService -> Retail.Business.Concretes.OrderService 時引發異常。 ---> Autofac.Core.DependencyResolutionException:檢測到循環組件依賴項:Retail.Business.Concretes.AfterSaleService -> Retail.Business.Concretes.OrderService -> Retail.Business.Concretes.AfterSaleService。

使用以下堆棧跟蹤:

   at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
   at Autofac.Core.Resolving.Pipeline.DefaultResolveRequestContext.ResolveComponent(ResolveRequest request)
   at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass0_0.<CanSupplyValue>b__0()
   at Autofac.Core.Activators.Reflection.BoundConstructor.Instantiate()
   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Activators.Reflection.ReflectionActivator.<ConfigurePipeline>b__11_0(ResolveRequestContext ctxt, Action`1 next)
   at Autofac.Core.Resolving.Middleware.DelegateMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   --- End of inner exception stack trace ---
   at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.RegistrationPipelineInvokeMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.SharingMiddleware.<>c__DisplayClass5_0.<Execute>b__0()
   at Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid id, Func`1 creator)
   at Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid primaryId, Nullable`1 qualifyingId, Func`1 creator)
   at Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
   at Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(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, Object& 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.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method429(Closure , IServiceProvider , Object[] )
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)   

我的 IoC 如下。 我說 IAfterService 在以下服務的構造函數中不起作用

public class ContainerModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {

        builder.RegisterType<AfterSaleService>().As<IAfterSaleService>().SingleInstance();
        builder.RegisterType<EfAfterSaleDal>().As<IAfterSaleDal>().SingleInstance();

        builder.RegisterType<ProductService>().As<IProductService>().SingleInstance();
        builder.RegisterType<EfProductDal>().As<IProductDal>().SingleInstance();

        builder.RegisterType<CustomerService>().As<ICustomerService>().SingleInstance();
        builder.RegisterType<EfCustomerDal>().As<ICustomerDal>().SingleInstance();

        builder.RegisterType<OrderService>().As<IOrderService>().SingleInstance();
        builder.RegisterType<EfOrderDal>().As<IOrderDal>().SingleInstance();

        builder.RegisterType<EfOrderDetailDal>().As<IOrderDetailDal>().SingleInstance();
        builder.RegisterType<OrderDetailService>().As<IOrderDetailService>()
            .SingleInstance();
    }
}

但它適用於控制器的構造函數

private IAfterSaleService _afterSaleService;

public AfterSalesController(IAfterSaleService afterSaleService)
{
    _afterSaleService = afterSaleService;
}

它在與 AfterService.cs 相同的服務目錄下不起作用,我希望它在 OrderService.cs 中工作,因為我需要它 注意:其他服務(如 ICustomerService、IProductService...)在 OrderService 的構造函數中工作,只有 IAfterSaleService 可以不行

    public class OrderService : IOrderService
    {
        private IOrderDal _orderDal;
        private ICustomerService _customerService;
        private IProductService _productService;
        private IOrderDetailService _orderDetailService;
        private IAfterSaleService _afterSaleService;

        public OrderService(
            IOrderDal orderDal,
            ICustomerService customerService,
            IProductService productService,
            IOrderDetailService orderDetailService,
            IAfterSaleService afterSaleService)
        {
            _orderDal = orderDal;
            _customerService = customerService;
            _productService = productService;
            _orderDetailService = orderDetailService;
            _afterSaleService = afterSaleService;
        }
    }

售后服務文件

    public class AfterSaleService : IAfterSaleService
    {
        private IAfterSaleDal _afterSaleDal;
        private IOrderService _orderService;

        public AfterSaleService(
            IAfterSaleDal afterSaleDal, IOrderService orderService)
        {
            _afterSaleDal = afterSaleDal;
            _orderService = orderService;
        }
    }

錯誤很明顯:

檢測到循環組件依賴性

你的AfterSaleService依賴於IOrderServiceOrderService依賴於IAfterSaleService很明顯,這將使 DI 容器在構建過程中無法解決依賴關系。 就我個人而言,我盡量不注入相同“級別”的依賴項,即存儲庫不接受存儲庫、服務 - 服務和控制器不依賴於其他控制器,因此我的建議是重構您的應用程序,這樣您就不需要這樣的注入(也許再引入一層或將公共代碼移動到靜態助手或其他東西)。

如果由於工作量大而無法重寫 ATM,您現在可以使用解決該問題的方法 - 注入與Func相同級別的依賴項。 Autofac提供開箱即用的Func解析(即,如果您注冊IService ,則無需任何額外注冊即可解析Func<IService> ),因此您可以執行以下操作:

public OrderService(..., Func<IAfterSaleService> afterSaleServiceFactory)
{
    .... 
    _afterSaleService = new Lazy<IAfterSaleService>(afterSaleServiceFactory);
}

public AfterSaleService(IAfterSaleDal afterSaleDal, 
     Func<IOrderService> orderServiceFactory)
{
    _afterSaleDal = afterSaleDal;
    _orderService = new Lazy<IAfterSaleService>(orderServiceFactory);
}

並使用延遲解析的依賴項 - _afterSaleService .Value , _orderService.Value

UPD

實際上似乎 Autofac 也支持開箱即用的Lazy ,所以這可以更容易:

public OrderService(..., Lazy<IAfterSaleService> afterSaleServiceFactory)
{
    .... 
    _afterSaleService = afterSaleService;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM