2016-10-13 63 views
0

我試圖使用Autofac實現以下依賴注入場景。推遲使用Autofac註冊財產

假設我有三個類,A,B和P.類A擁有P類型的屬性,並且還具有對B的引用,它需要在運行時注入。

class A 
{ 
    private B _b; 

    public P Prop { get; set; } 

    InitializeProp() 
    { ... } 
} 

同時,B類取決於P的實例:

class B 
{ 
    private P _p; 
} 

現在,最重要的細節:我需要以某種方式注入分爲B P的一個實例然而,實例必須是來自A類的Prop,該類只在調用A中的InitializeProp()後才初始化。假設InitializeProp()可以在對象的生命週期中晚於A的構造函數調用。

Autofac可以實現這種情況嗎?

我試圖做這樣的事情,但我得到一個循環引用例外,想必當B是進一步解決:

containerBuilder.RegisterType<A>().SingleInstance(); 

containerBuilder.Register<Func<P>>(c => 
{ 
    var a = c.Resolve<A>(); 
    return() => a.Prop; 
}); 

回答

0

所以最終我想通了,原來Autofac比聰明我想。

這是沒有必要明確登記P的Func,而是有這樣的簡化註冊:

builder.RegisterType<A>().SingleInstance(); 

builder.Register(c => 
{ 
    var a = c.Resolve<A>(); 
    return a.Property; 
}); 

builder.RegisterType<B>(); 

現在在主程序中,我可以做到以下幾點:

var a = container.Resolve<A>(); 
a.InitializeProperty(); 
a.Execute(); // calls B 
2

爲了能夠掌握registrational問題,我常常覺得有用構建手工編碼所需的對象圖。不使用DI容器的,這是你希望達到什麼目的:

var p = new P(); 
var a = new A(new B(p)) { P = p }; 

你能看到的是,中P實例在整個圖形重複使用,以實現這一目標。有了這些知識,我們現在可以確定你需要做什麼來實現你想要的。

因此,解決方案是配置Autofac重用P的同一個實例。由於您註冊ASingleInstance,除了註冊PSingleInstance以外,沒有其他選擇,否則您將處理Captive Dependency

但是,如果我們退後一步,我看不到PA的財產的理由。事實上,有hardly ever a good reason使用屬性注入。

你應該總是使用構造函數注入。所以,你的類應該如下所示:

class A { public A(B b, P p) { } } 
class B { public B(P p) { } } 

這完全刪除配置的麻煩,因爲你可以簡單地做到以下幾點:

containerBuilder.RegisterType<A>().SingleInstance(); 
containerBuilder.RegisterType<B>().SingleInstance(); 
containerBuilder.RegisterType<P>().SingleInstance(); 
+0

理想我按照你的建議設計我的課程,P通過A和B中的構造函數注入。然而,我的真實場景受到其他依賴性的限制,並且長話短說,沒有辦法規避A級中的屬性P,該屬性在A的一生中的某個點被初始化。 A實現了一個聲明屬性P的接口。 –