理论上,不必担心拥有静态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