我最近將Autofac添加到一個大型的現有應用程序來管理DI。Autofac報告不存在的循環依賴關係
在這個過程中,我用被注入到從屬構造函數的容器管理的單個實例替換了單例。然而,在某些情況下,必須打破循環依賴。我發現最簡單的方法是利用OnActivated事件。我們打算修改這些類型以消除循環依賴,但現在改變它們的風險太大了。
要參與循環依賴的類型,I添加了一個名爲方法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模塊中,與負載方法如下:
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的詳細問題:) – 2011-01-12 17:33:23