5

的autofac wiki頁面約Circular References說,使用:如何使用Autofac 2.4.5處理循環引用?

cb.Register<DependsByProp>().OnActivated(ActivatedHandler.InjectUnsetProperties); 

但它看起來像ActivatedHandler不會在2.4.5存在了。在源代碼中挖掘,我發現該類的實現,所以我將方法實現放在OnActivated中。不幸的是,這仍然行不通。

我已經放在一起這裏看起來像維基頁面上的最小repro。

class M 
{ 
    public VM VM { get; set; } 

    public M() 
    { 
    } 
} 

class VM 
{ 
    public VM(M m) 
    { 
    } 
} 

[Fact] 
void CanResolveCircular() 
{ 
    ContainerBuilder builder = new ContainerBuilder(); 

    builder.RegisterType<VM>(); 
    builder.RegisterType<M>().OnActivated(e => e.Context.InjectUnsetProperties(e.Instance)); 

    using (var container = builder.Build()) 
    { 
     var m = container.Resolve<M>(); 
     Assert.NotNull(m); 
    } 
} 

該代碼在嘗試解析時仍然會引發堆棧溢出異常。我錯過了什麼?讓Autofac處理循環依賴的正確方法是什麼?

+0

是。我認爲循環依賴意味着與實例循環相同。下面的答案指出了我錯過了類和實例之間的循環依賴關係的概念。 – Ants 2011-05-31 17:18:37

回答

7

的Autofac文檔circular dependencies狀態:

注意,它沒有意義設立 這種情況下,如果兩個類都 與廠範圍內註冊。

無論您M和​​註冊被InstancePerDependency(以前稱爲FactoryScope),所以此聲明適用於您的方案。因此,您會陷入無休止的創建M和VM實例的循環。

如果您希望屬性注入​​採取同一個實例的M你解決,你應該的M壽命更改爲InstancePerDependency(例如SingleInstance)以外的東西。這是如下圖所示:

builder.RegisterType<M>().PropertiesAutowired(true).SingleInstance(); 

注:我還使用了較新的PropertiesAutowired(真)擴展方法。你可以用它來代替你的repro中的OnActivated代碼。

如果你不希望的M每個應用的單一實例,你可以設置一個LifetimeScope和使用InstancePerLifetimeScope

5

任何有興趣在這裏是這樣做的新方法:

class DependsByProp1 
{ 
    public DependsByProp2 Dependency { get; set; } 
} 

class DependsByProp2 
{ 
    public DependsByProp1 Dependency { get; set; } 
} 

// ... 

var cb = new ContainerBuilder(); 
cb.RegisterType<DependsByProp1>() 
     .InstancePerLifetimeScope() 
     .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies); 
cb.RegisterType<DependsByProp2>() 
     .InstancePerLifetimeScope() 
     .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies); 

Property/Property Dependencies