Autofac报告不存在的循环依赖项
我最近将Autofac添加到一个大型的现有应用程序来管理DI.
在这个过程中,我用一个由容器管理的单个实例替换了单例,这个实例被注入到依赖的构造函数中.但是,在某些情况下,必须打破循环依赖关系.我发现这样做的最简单方法是利用OnActivated事件.我们打算修改这些类型以消除循环依赖关系,但现在更改它们的风险太大了. 对于循环依赖关系中涉及的类型,我添加了一个名为ResolveCircularDependencies的方法(这很明显,这个方法只是暂时使用,目的是解决这些循环).在OnActivated事件中调用此方法. 所以我的代码现在看起来像这样: public class ServiceA { private ServiceB otherService; public ServiceA() { ... } public void ResolveCircularDependencies(ServiceB other) { this.otherService = other; } public void SomeMethod() { ... this.otherService.SomeMethod(); ... } } public class ServiceB { private ServiceA otherService; public ServiceB() { ... } public void ResolveCircularDependencies(ServiceA other) { this.otherService = other; } public void SomeMethod() { ... this.otherService.SomeMethod(); ... } } 这些类型在Autofac模块中注册,Load方法如下: public override void Load(ContainerBuilder builder) { builder .Register(ctx => new ServiceA()) .OnActivated(e => e.Instance.ResolveCircularDependences(e.Context.Resolve<ServiceB>())); builder .Register(ctx => new ServiceB()) .OnActivated(e => e.Instance.ResolveCircularDependences(e.Context.Resolve<ServiceA>())); } 在大多数情况下,这似乎可以正常工作.但是,我们随机看到Autofac认为它已找到循环依赖并返回以下堆栈跟踪,但有异常: at Autofac.Core.Resolving.CircularDependencyDetector.CheckForCircularDependency(IComponentRegistration registration,Stack`1 activationStack,Int32 callDepth) at Autofac.Core.Resolving.ResolveOperation.Resolve(ISharingLifetimeScope activationScope,IComponentRegistration registration,IEnumerable`1 parameters) at Autofac.Core.Resolving.ComponentActivation.Resolve(IComponentRegistration registration,IEnumerable`1 parameters) at Autofac.ResolutionExtensions.TryResolve(IComponentContext context,Service service,IEnumerable`1 parameters,Object& instance) at Autofac.ResolutionExtensions.Resolve(IComponentContext context,IEnumerable`1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context,IEnumerable`1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context) at DomainObjectFactory.Resolve[T]() at DomainObjectFactory.BuildMyObject() 我们还随机看到以下错误: at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) at System.Collections.Generic.Stack`1.Enumerator.MoveNext() at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source,Func`2 predicate) at Autofac.Core.Resolving.CircularDependencyDetector.IsCircularDependency(IComponentRegistration registration,Stack`1 activationStack) at Autofac.Core.Resolving.CircularDependencyDetector.CheckForCircularDependency(IComponentRegistration registration,IEnumerable`1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context) at DomainObjectFactory.Resolve[T]() at DomainObjectFactory.BuildMyObject() 所有注册完成后都会发生这种情况(在应用程序启动时在单个线程上发生).可以在单独的线程上同时调用BuildMyObject方法.然而,根据Autofac wiki,这似乎是可以接受的. 我已经查看了ServiceA和ServiceB的完整依赖树,并且对象树中没有循环. 有没有人见过这种行为?分辨率是多少? 我们正在使用Autofac 2.3.2.632-NET35发布下载here. 解决方法
您的DomainObjectFactory正在调用的IComponentContext似乎是在单个解析操作期间创建的临时文件,例如,c参数如下:
builder.Register(c => new DomainObjectFactory(c)) 这些不是线程安全的;正确的代码是: builder.Register(c => new DomainObjectFactory(c.Resolve<IComponentContext>()) 这是一个令人讨厌的陷阱,偶尔出现,但通常是可检测的,因为一旦c被释放,Resolve()调用将抛出告诫ObjectDisposedException.我将在你链接到的并发页面上做一个注释. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |