Autofac循环依赖

时间:2017-06-21 09:01:26

标签: autofac circular-dependency

尝试使用Autofac构建以下内容时出现循环依赖项异常:

        builder.RegisterType<Session>().As<ISession>();
        builder.RegisterType<SFEventStore>().As<IEventStore>();
        builder.RegisterType<MemoryCache>().As<ICache>();
        builder.Register(c =>
        {
            return new CacheRepository(new Repository(c.Resolve<IEventStore>()), c.Resolve<IEventStore>(), c.Resolve<ICache>());

        })
        .As<IRepository>();

问题是IRepository,它解析为CacheRepository,而CacheRepository依赖于IRepository:

public CacheRepository(IRepository repository, IEventStore eventStore, ICache cache);

Repository在其构造函数中使用IEventStore:

    public class Repository : IRepository
    {
        private readonly IEventStore _eventStore;

        public Repository(IEventStore eventStore)
        {
            _eventStore = eventStore ?? throw new ArgumentNullException(nameof(eventStore));
        }
    }

CacheRepository遵循装饰器模式并向存储库添加功能:

public class CacheRepository : IRepository
    {
        private readonly IRepository _repository;
        private readonly IEventStore _eventStore;
        private readonly ICache _cache;

        public CacheRepository(IRepository repository, IEventStore eventStore, ICache cache)
        {
            _repository = repository ?? throw new ArgumentNullException(nameof(repository));
            _eventStore = eventStore ?? throw new ArgumentNullException(nameof(eventStore));
            _cache = cache ?? throw new ArgumentNullException(nameof(cache));

        }

因此,尽管我在Autofac构建器方法中新建了一个Repository,但Autofac仍然会尝试解析CacheRepository构造函数中的IRepository,该构造函数解析为CacheRepository。因此循环依赖。

尝试使用Autofac装饰器解决此问题,如下所示:

        builder.RegisterType<Session>().As<ISession>();
        builder.RegisterType<SFEventStore>().As<IEventStore>();
        builder.RegisterType<MemoryCache>().As<ICache>();
        builder.Register(c =>
        {
            return new Repository(c.Resolve<IEventStore>());
        })
        .Named<IRepository>("implementor");

        builder.RegisterDecorator<IRepository>(
            (c, inner) => new CacheRepository(inner, c.Resolve<IEventStore>(), c.Resolve<ICache>()),
            fromKey: "implementor");

但没有运气。仍然给出循环依赖!

该链从解析会话开始,该会话具有以下ctor:

public Session(IRepository repository);

所以我应该得到以下组件依赖树:

Session --> CacheRepository --> Repository --> SFEventStore

但它转而解决:

Session --> CacheRepository --> CacheRepository

这是堆栈跟踪:

Autofac.Core.DependencyResolutionException:检测到循环组件依赖关系:AnswersBC.Command.Handlers.AddAnswerCmdHandler - &gt; CQRSlite.Domain.Session - &gt; CQRSlite.Cache.CacheRepository - &gt; CQRSlite.Cache.CacheRepository。在Autofac.Core.Resolving.CircularDependencyDetector.CheckForCircularDependency(IComponentRegistration注册,堆栈1 activationStack, Int32 callDepth) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable 1个参数)在C:\ BuildAgent \工作\ 3206e2123f54fce4 \ SRC \ NServiceBus.Core \许可\ LogErrorOnInvalidLicenseBehavior.cs:在Autofac线0。 Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()位于C:\ BuildAgent \ work \ 3206e2123f54fce4 \ src \ NServiceBus.Core \ Licensing \ LogErrorOnInvalidLicenseBehavior.cs:第0行,位于Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context) ,IEnumerable的1 parameters) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable 1个参数)在C:\ BuildAgent \工作\ 3206e2123f54fce4 \ SRC \ NServiceBus.Core \许可\ LogErrorOnInvalidLicenseBehavior.cs:行0在Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(GUID ID,Func键{ {1}} 1个参数)在C:\ BuildAgent \ work \ 3206e2123f54fce4 \ src \ NServiceBus.Core \ Licensing \ LogErrorOnInvalidLicenseBehavior.cs:第0行,位于C:\ BuildA中的Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()绅士\工作\ 3206e2123f54fce4 \ SRC \ NServiceBus.Core \许可\ LogErrorOnInvalidLicenseBehavior.cs:行0在Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext上下文,IEnumerable的1 creator) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Execute() in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable 1个参数)在C:\ BuildAgent \ work \ 3206e2123f54fce4 \ src \ NServiceBus.Core \ Licensing \ LogErrorOnInvalidLicenseBehavior.cs:在C:\ BuildAgent \ work \中的Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id,Func 1 parameters) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable 1个参数)的第0行3206e2123f54fce4 \ src \ NServiceBus.Core \ Licensing \ LogErrorOnInvalidLicenseBehavior.cs:第0行,位于C:\ BuildAgent \ work \ 3206e2123f54fce4 \ src \ NServiceBus.Core \ Licensing \ LogErrorOnInvalidLicenseBehavior中的Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()。 CS:线0在Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext上下文,IEnumerable的1 creator) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Execute() in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable 1个参数)在C:\ BuildAgent \工作\ 3206e2123f54fce4 \ SRC \ NServiceBus.Core \许可\ LogErrorOnInvalidLicenseBehavior.cs :第0行在Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(GUID标识,函数功能1 parameters) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable 1个参数)在C:\ BuildAgent \工作\ 3206e2123f54fce4 \ SRC \ NServiceBus.Core \许可\ LogErrorOnInvalidLicenseBehavior.cs:在Autofac线0。 Core.Resolving.ResolveOperation.Execute(IComponentRegistration注册,IEnumerable 1 creator) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Execute() in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable 1个参数,Object&amp;在C:\ BuildAgent \ work \ 3206e2123f54fce4 \ src \ NServiceBus.Core \ Licensing \ LogErrorOnInvalidLicenseBehavior.cs中:在C:\ BuildAgent \中的Autofac.ResolutionExtensions.ResolveService(IComponentContext上下文,服务服务,IEnumerable`1参数)中的第0行work \ 3206e2123f54fce4 \ src \ NServiceBus.Core \ Licensing \ LogErrorOnInvalidLicenseBehavior.cs:位于C:\ BuildAgent \ work \ 3206e2123f54fce4 \ src \ NServiceBus.Core \ ObjectBuilder \ Autofac \ AutofacObjectBuilder中的NServiceBus.AutofacObjectBuilder.Build(Type typeToBuild)的第0行。 cs:位于C:\ BuildAgent \ work \ 3206e2123f54fce4 \ src \ NServiceBus.Core \ Pipeline \ Incoming \ LoadHandlersConnector.cs:第37行的NServiceBus.LoadHandlersConnector.d__1.MoveNext()第39行

2 个答案:

答案 0 :(得分:1)

您描述的内容与Decorator模式完全相同。你有两个IRepository实现,一个包装另一个。 Autofac使用.RegisterDecorator()

本地支持此功能

请参阅此处的文档, http://docs.autofac.org/en/latest/advanced/adapters-decorators.html

我相信你的新问题就是问题,见下面的例子

不要使用它:

builder.Register(c =>
{
    return new Repository(c.Resolve<IEventStore>());
})
.Named<IRepository>("implementor");

而是使用它:

builder.RegisterType<Repository>().Named<IRepository>("implementor");
builder.RegisterDecorator<IRepository>(
        (c, inner) => new CacheRepository(inner, c.Resolve<IEventStore>(), c.Resolve<ICache>()),
        fromKey: "implementor");

答案 1 :(得分:0)

似乎必须对NServiceBus中组件的配置做一些事情:

        nsbEndpointConfig.RegisterComponents(registration: configureComponents =>
        {
            configureComponents.ConfigureComponent<Session>(DependencyLifecycle.InstancePerUnitOfWork);
            configureComponents.ConfigureComponent<SFEventStore>(DependencyLifecycle.InstancePerUnitOfWork);
            configureComponents.ConfigureComponent<MemoryCache>(DependencyLifecycle.InstancePerUnitOfWork);
            configureComponents.ConfigureComponent<Repository>(DependencyLifecycle.InstancePerUnitOfWork);
            configureComponents.ConfigureComponent<CacheRepository>(DependencyLifecycle.InstancePerUnitOfWork);
        });

当我省略此配置时,未检测到循环依赖性。我所做的就是设置生命望远镜。