3

当使用负责创建和管理图中对象生命周期的手工容器/注入器时,我使用以下模式(我在一篇关于 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 注入。

有什么解决办法吗?

4

3 回答 3

2

我会去工厂。
这似乎有点开销,但是如果您使用 TDD,它将大大简化您的生活,因为您可以轻松地模拟工厂并单独测试您的控制器。
它也适用于台风。

于 2013-12-05T17:58:57.107 回答
2

注入 TyphoonComponentFactory:

  • 您可以覆盖- (void)typhoonSetFactory:(id)theFactory类中的生命周期方法。
  • 在您的程序集界面中,您可以注入一个属性或参数self

在任何一种情况下,您的任何TyphoonAssembly界面都可以摆在工厂前面。因此,例如,如果您有一个名为 的程序集NetworkAssembly,您可以定义一个类型的属性NetworkAssembly并注入工厂。此功能的文档在此处

您可以使用这种方法来推出您自己的工厂:

  • 从容器中提取静态依赖项。
  • 通过从工厂接口注入静态依赖项以及运行时参数来实例化需求组件。

带有运行时参数的台风工厂:

您的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];

此功能的文档在此处

于 2013-12-06T01:07:34.460 回答
1

您的程序集接口可以用作工厂 - 提供静态依赖项以及运行时参数。此功能的文档在此处

例子:

- (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];
于 2014-02-19T20:50:47.333 回答