首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Autofac循环依赖

Autofac循环依赖
EN

Stack Overflow用户
提问于 2017-06-21 17:01:26
回答 2查看 1.4K关注 0票数 0

当我尝试用Autofac构建以下代码时,我得到一个循环依赖异常:

代码语言:javascript
复制
        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:

代码语言:javascript
复制
public CacheRepository(IRepository repository, IEventStore eventStore, ICache cache);

存储库在其构造函数中接受一个IEventStore:

代码语言:javascript
复制
    public class Repository : IRepository
    {
        private readonly IEventStore _eventStore;

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

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

代码语言:javascript
复制
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 builder方法中新建了一个存储库,Autofac仍然尝试在CacheRepository构造函数中解析IRepository,该构造函数解析为CacheRepository。因此出现了循环依赖。

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

代码语言:javascript
复制
        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:

代码语言:javascript
复制
public Session(IRepository repository);

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

代码语言:javascript
复制
Session --> CacheRepository --> Repository --> SFEventStore

但相反,它解析为:

代码语言:javascript
复制
Session --> CacheRepository --> CacheRepository

这是堆栈跟踪:

Autofac.Core.DependencyResolutionException:检测到循环组件依赖项: AnswersBC.Command.Handlers.AddAnswerCmdHandler -> CQRSlite.Domain.Session -> CQRSlite.Cache.CacheRepository -> CQRSlite.Cache.CacheRepository。在Autofac.Core.Resolving.CircularDependencyDetector.CheckForCircularDependency(IComponentRegistration注册时,在C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line上下文的Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()处的C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0中的Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext 0中栈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, IEnumerable1参数),在Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid _ id处的C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line _0中的函数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参数),在Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext _ context处的Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate() _ in _ C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line _0中的Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext_0中的IEnumerable_1 parameters) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable_1参数),在Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid _ id处的C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line _0中的函数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参数),在Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext _ context处的Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate() _ in _ C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line _0中的Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext_0中的IEnumerable_1 parameters) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable_1参数),在Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration注册时的C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0中的函数1 parameters) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1参数),在Autofac.ResolutionExtensions.ResolveService(IComponentContext上下文中的C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0中的IEnumerable1 parameters) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1参数,对象和实例),服务服务,IEnumerable`1个参数)在C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Licensing\LogErrorOnInvalidLicenseBehavior.cs:line 0中,位于C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\ObjectBuilder\Autofac\AutofacObjectBuilder.cs:line 39中的NServiceBus.LoadHandlersConnector.d__1.MoveNext() (类型为typeToBuild),位于C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Pipeline\Incoming\LoadHandlersConnector.cs:line 37中

EN

回答 2

Stack Overflow用户

发布于 2017-06-21 20:07:33

你所描述的听起来就像是装饰者模式。您有两个IRepository实现,一个包装了另一个。Autofac使用.RegisterDecorator()本机支持这一点

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

我相信你的“新”设置就是问题所在,请看下面的例子。

不要使用以下命令:

代码语言:javascript
复制
builder.Register(c =>
{
    return new Repository(c.Resolve<IEventStore>());
})
.Named<IRepository>("implementor");

取而代之的是:

代码语言:javascript
复制
builder.RegisterType<Repository>().Named<IRepository>("implementor");
builder.RegisterDecorator<IRepository>(
        (c, inner) => new CacheRepository(inner, c.Resolve<IEventStore>(), c.Resolve<ICache>()),
        fromKey: "implementor");
票数 1
EN

Stack Overflow用户

发布于 2017-06-22 19:52:47

似乎必须对NServiceBus中的组件进行一些配置:

代码语言:javascript
复制
        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);
        });

当我省略这个配置时,没有检测到循环依赖。但是,我在这里所做的只是设置生命周期范围。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44671464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档