2

当我的应用程序启动时,我会获取一个远程配置文件,其中包含配置其他依赖项所需的信息(URL 等)。

获取远程配置后,我有一个Config需要提供给其他TyphoonDefinitions 的对象。

现在我也在使用 plist 故事板集成。

我最初是沿着将程序集注入加载 Config 对象的 ViewController 的路径,当我收到远程配置并创建 Config 对象时,我会以某种方式将其设置为程序集的属性。我这样做是希望我可以在定义中使用该属性,但这不起作用,我得到:

2014-10-22 21:18:06.203 four[39840:516543] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'No component matching id 'setConfig:'.'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010a3e63f5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010a07fbb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010a3e632d +[NSException raise:format:] + 205
    3   four                                0x00000001070a011d -[TyphoonComponentFactory componentForKey:args:] + 148
    4   CoreFoundation                      0x000000010a2de22c __invoking___ + 140
    5   CoreFoundation                      0x000000010a2de082 -[NSInvocation invoke] + 290
    6   CoreFoundation                      0x000000010a36d456 -[NSInvocation invokeWithTarget:] + 54
    7   four                                0x000000010709d358 -[TyphoonBlockComponentFactory forwardInvocation:] + 276

有什么方法可以让我在运行时将对象注入到程序集中?

有没有更清洁的方法来做我想做的事情?

我正在阅读听起来像我需要的运行时参数,但我真的不理解文档。

例如,我有这个作为定义。我需要将运行时 Config 对象作为参数传递给构造函数。

- (id<ApiService>)apiService
{
    return [TyphoonDefinition withClass:[ApiService class] configuration:^(TyphoonDefinition* definition) {}];
}
4

2 回答 2

2

使用运行时参数

例如,我有这个作为定义。我需要将运行时 Config 对象作为参数传递给构造函数。

- (id<ApiService>)apiService {
return [TyphoonDefinition withClass:[ApiService class] configuration:^(TyphoonDefinition* definition) {}]; }

尝试这样的事情:

- (id<ApiService>)apiServiceWithConfig:(Config *)config {
    return [TyphoonDefinition withClass:[ApiService class] configuration:^(TyphoonDefinition* definition) {

        // inject into property: 
        [definition injectProperty:@selector(config) with:config];

        // inject into constructor:
        [definition useInitializer:@selector(initWithConfig:) parameters:^(TyphoonMethod *initializer) {
            [initializer injectParameterWith:config];
        }];

    }]; 
}

使用工厂定义

看看接下来的两个定义:

- (Config *)currentConfig {
    return [TyphoonDefinition withFactory:[self configManager] selector:@selector(currentConfig)];
}

 - (ConfigManager *)configManager {
     return [TyphoonDefinition withClass:[ConfigManager class] configuration:^(TyphoonDefinition *definition){
         definition.scope = TyphoonScopeSingleton;
     }];
 }

想象一下,您有一个 ConfigManager,它下载远程配置并将其存储为“currentConfig”属性,“configManager”定义描述了该对象。

然后检查“currentConfig”定义。此定义仅返回在 ConfigManager 实例上调用 'currentConfig' 方法的结果。

然后你可以注入配置为:

- (id<ApiService>)apiService {
    return [TyphoonDefinition withClass:[ApiService class] configuration:^(TyphoonDefinition* definition) {
        [definition injectProperty:@selector(config) with:[self currentConfig]];
    }]; 
}

但请确保在“apiService”创建期间加载了 currentConfig(不是 nil)。(也许更好地注入 ConfigManager - 然后如果 currentConfig nil,它将在稍后填充)

于 2014-10-23T04:02:46.183 回答
1

几点:

  • 运行时参数是超酷的功能,真正有助于获得 Typhoon 的全部功能。我们强烈建议您了解它们(如果您愿意,可以在这里提问)。但是,它们不适合您尝试做的事情。
  • 可以使用以下方法在运行时在容器中注册新定义:

.

- (void)registerDefinition:(TyphoonDefinition *)definition;

. . 你可能也不想在你的情况下这样做。


你感兴趣的是

TyphoonComponentFactoryPostProcessor 和 TyphoonComponentPostProcessor:

Typhoon 有两种可以附加的接口,一种是TyphoonComponentFactoryPostProcessor,另一种是TyphoonComponentPostProcessor。它们在内部使用,但您也可以自己编写并用它们做各种很酷的事情。

  • TyphoonComponentFactoryPostProcessor:在构建之前修改组件的定义(配方)。

  • TyphoonComponentPostProcessor:实例构建后对其进行修改。


台风配置:

有一个现有的 TyphoonComponentFactoryPostProcessor 可用于您描述的任务。它称为TyphoonConfigPostProcessor,并在此处的用户指南中进行了描述

所有后处理器都可以在构建时(在程序集中)或在运行时附加,如下所示:

TyphoonConfigPostProcessor* configurer = [[TyphoonConfigPostProcessor alloc] init];
[configurer useResourceWithName:@"Configuration.plist"]];
[factory attachPostProcessor:configurer];


请注意,由于 TyphoonComponentFactoryPostProcessor 修改了定义,如果您有已经构建的单例范围的组件,它们不会受到影响。你必须要么创建惰性单例,要么调用[factory unload].


启动后如何获取对 TyphoonComponentFactory 的引用?

无论您的应用程序中哪个正在执行配置步骤,都需要设置为“Typhoon Aware”。您可以使用以下方法执行此操作:

- (ConfigController *)configController
{
    return [ConfigController withClass:[INFGiftDeliveryAddressController class] 
        configuration:^(TyphoonDefinition *definition)
    {        
        [definition injectProperty:@selector(factory) with:self];
    }];

. . 注入程序集时,您可以声明类型的属性TyphoonComponentFactory或任何程序集子类。无论哪种方式,它都会起作用。此功能的文档在此处

在移动和桌面应用程序中,您的组件通常需要“感知台风”,以便我们可以从一个对象图(例如视图控制器)继续到另一个对象图(这就是运行时参数功能有用的地方) . 请注意,您正在编写自己的特定于域的程序集接口,因此 Typhoon 是“非侵入性的”。在大多数情况下,您的应用程序不直接引用任何 Typhoon API。

我们在这里介绍了很多内容,因此如果您有任何其他问题或需要澄清,请随时提出。

于 2014-10-23T02:52:49.417 回答