【发布时间】:2010-11-15 21:17:32
【问题描述】:
我最近将 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, Service service, 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, 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, Service service, 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()
在所有注册完成后(在应用程序启动时发生在单个线程上),这些都会很好地发生。 BuildMyObject 方法的调用可以在不同的线程上同时进行。但是,根据Autofac wiki,这似乎是可以接受的。
我查看了ServiceA和ServiceB的完整依赖树,对象树中没有循环。
有人见过这种行为吗?分辨率是多少?
我们正在使用 Autofac 2.3.2.632-NET35 发布供下载here。
【问题讨论】:
-
+1 获取详细问题 :)
标签: autofac