理論上,不必擔心擁有靜態IoC實例,您需要遵循搏擊俱樂部規則 - 即不要談論戰鬥俱樂部 - 即不提及IoC容器。
這意味着您的組件應該很大程度上不了解IoC容器。它只能在註冊組件時在最高層使用。如果一個類需要解析某些東西,那麼它應該真的作爲一個依賴注入。
瑣碎的情況很簡單。如果PaymentService
取決於IAccount
,後者應該由IoC來注入:
interface IAccount {
Deposit(int amount);
}
interface CreditCardAccount : IAccount {
void Deposit(int amount) {/*implementation*/}
int CheckBalance() {/*implementation*/}
}
class PaymentService {
IAccount account;
public PaymentService (IAccount account) {
this.account = account;
}
public void ProcessPayment() {
account.Deposit(5);
}
}
//Registration looks something like this
container.RegisterType<IAccount, CreditCardAccount>();
container.RegisterType<PaymentService>();
不那麼簡單的情況就是要注入多個註冊。特別適用於任何類型的Converntion Over Configuration並通過名稱創建對象。
有關付款例如,假設你想通過所有帳戶枚舉並檢查他們的餘額:
class PaymentService {
IEnumerable<IAccount> accounts;
public PaymentService (IEnumerable<IAccount> accounts) {
this.accounts = accounts;
}
public void ProcessPayment() {
foreach(var account in accounts) {
account.Chackbalance();
}
}
}
團結有註冊多個接口類的映射(他們必須有不同的名字還以爲)的能力。但是,它不會自動將它們注入到那些註冊接口集合的類中。所以,上面的例子會在運行時拋出一個解決失敗的異常。
如果你不在乎這些對象永遠活着,你可以在一個更靜態的方式登記PaymentService
:
container.RegisterType<PaymentService>(new InjectionConstructor(container.ResolveAll<IAccount>()));
上面的代碼將註冊PaymentService
並會使用IAccount
實例的集合,即解決在註冊時。
或者,您可以傳遞容器本身的一個實例作爲依賴關係,並讓PaymentService
執行帳戶的解析。這並不完全符合撲克俱樂部規則,但比靜態服務定位器稍微有點臭。
class PaymentService {
IEnumerable<IAccount> accounts;
public PaymentService (IUnityContainer container) {
this.accounts = container.ResolveAll<IAccount>();
}
public void ProcessPayment() {
foreach(var account in accounts) {
account.Chackbalance();
}
}
}
//Registration is pretty clean in this case
container.RegisterType<IAccount, CreditCardAccount>();
container.RegisterType<PaymentService>();
container.RegisterInstance<IUnityContainer>(container);
開始賞金,對不起點的低量,但我只有一個賺了:-) – Michel 2010-06-20 12:21:59
如果您想更詳細的治療我正在寫一本關於它的書:http://www.manning.com/seemann/ – 2010-06-25 08:52:25