当使用手工制作的容器/注射器负责创建和管理图形中对象的生命周期时,我使用以下模式(我在ObjC中的一篇关于DIY DI的文章中读到):
假设我们有一个根视图控制器想要呈现另一个(让它称之为详细视图控制器)将一些数据传递给它。我通常做的是注入一个提供程序块,它将数据作为参数并返回一个新的视图控制器来呈现。这是一些代码...
@implementation RootViewController
{
UIViewController (^detailViewControllerProvider)(SomeData *someData);
}
- (id) initWithDetailViewControllerProvider:(UIViewController (^)(SomeData *someData))detailViewControllerProvider
{
//...
_detailViewControllerProvider = detailViewControllerProvider;
//...
}
// ...
- (void) presentDetailViewControllerWithData:(SomeData *)someData
{
UIViewController *detailViewController = _detailViewControllerProvider(someData);
[self presentViewController:detailViewController animated:YES completion:nil];
}
@end
我也可以使用工厂类,但这样我就可以避免在我的容器类中创建一个新的类。
当我想将Typhoon用作DI容器时,问题出现了。我怎样才能使用相同的模式?在我的详细视图控制器中,我正在注入其他东西,我想继续使用构造函数注入,并且更喜欢它是由组件工厂创建的,而不是由我创建的。我可以创建一个工厂类来创建详细信息VC,在我的详细信息VC中注入我想要注入的依赖项(工厂),但与基于块的解决方案相比,这似乎太多了。
我不想从根视图控制器访问我的组件工厂,也不想对someData使用setter注入。
有没有解决方案?
答案 0 :(得分:2)
我会去工厂。
这似乎有点开销,但如果你做TDD,它将大大简化你的生活,因为你可以轻松地模拟工厂并单独测试你的控制器。
它也适用于台风。
答案 1 :(得分:2)
注入TyphoonComponentFactory:
- (void)typhoonSetFactory:(id)theFactory
。 self
在任何一种情况下,任何TyphoonAssembly
接口都可以在工厂前摆出姿势。因此,例如,如果您有一个名为NetworkAssembly
的程序集,则可以定义类型为NetworkAssembly
的属性,并将该工厂注入其中。此功能的文档为here。
您可以使用此方法来推销自己的工厂:
Typhoon Factories w / Runtime Arguments:
您的TyphoonAssembly
接口现在可以实现上述模式:
示例:
- (UserDetailsController *)userDetailsControllerForUser:(User *)user
{
return [TyphoonDefinition withClass:[UserDetailsViewController class]
configuration:^(TyphoonDefinition *definition) {
[definition useInitializer:@selector(initWithPhotoService:user)
parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:[self photoService];
[initializer injectParameterWith:user];
}];
}];
}
现在解决该组件:
User* aUser = self.selectedUser;
UserDetailsViewController* detailsController =
[assembly userDetailsControllerForUser:aUser];
此功能的文档为here。
答案 2 :(得分:1)
您的程序集接口可以充当工厂 - 提供静态依赖项以及运行时参数。此功能的文档为here。
示例:强>
- (UserDetailsController *)userDetailsControllerForUser:(User *)user
{
return [TyphoonDefinition withClass:[UserDetailsViewController class]
configuration:^(TyphoonDefinition *definition) {
[definition useInitializer:@selector(initWithPhotoService:user)
parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:[self photoService];
[initializer injectParameterWith:user];
}];
}];
}
现在解决该组件:
User* aUser = self.selectedUser;
UserDetailsViewController* detailsController =
[assembly userDetailsControllerForUser:aUser];