如何使用Typhoon将运行时参数传递给子组件?

时间:2014-12-09 20:05:05

标签: objective-c typhoon

我们说我有两个班级FooBar。我可以独立于Bar构建Foo,但Foo需要Bar。在Typhoon中,我定义了这两个组件并在我的应用程序中使用它们,但是在运行时,在构建Foo时,我传入的barId似乎传递给另一个Bar组件作为<TyphoonInjectionByRuntimeArgument: 0x15ea4670, type=Undifined>而不是我传入的NSString

我可能做错了。

我应该采取哪些不同的方式?

@implementation Assembly

-(Foo *)fooWithFooId:(NSString *)fooId andBarId:(NSString *)barId {
  return [TyphoonDefinition withClass:[Foo class] configuration:^(TyphoonDefinition* definition) {
    [definition useInitializer:@selector(initWithFooId:andBar:) parameters:^(TyphoonMethod *initializer) {
        [initializer injectParameterWith:fooId];
        [initializer injectParameterWith:[self barWithId:barId]];
    }];
  }];
}

-(Bar *)barWithBarId:(NSString *)barId {
  return [TyphoonDefinition withClass:[Bar class] configuration:^(TyphoonDefinition* definition) {
    [definition useInitializer:@selector(initWithBarId:) parameters:^(TyphoonMethod *initializer) {
      [initializer injectParameterWith:barId];
    }];
  }];
}

@end

////////

@implementation Foo

-(instancetype) initWithFooId:(NSString *)fooId andBar:(Bar *)bar
{
  self = [super init];
  self.fooId = fooId;
  self.bar = bar;
  return self;
}

@end

@implementation Bar

-(instancetype) initWithBarId:(NSString *)barId
{
  self = [super init];
  self.barId = barId;
  return self;
}

@end

更新

经过进一步审核后,问题似乎是由定义中的运行时参数为另一个定义构建另一个参数引起的。请参阅下面NSString的用法:

@implementation Assembly

-(Foo *)fooWithFooId:(NSString *)fooId andBazId:(NSString *)bazId {
  return [TyphoonDefinition withClass:[Foo class] configuration:^(TyphoonDefinition* definition) {
    [definition useInitializer:@selector(initWithFooId:andBaz:) parameters:^(TyphoonMethod *initializer) {
        [initializer injectParameterWith:fooId];
        [initializer injectParameterWith:[self bazWithPathToBaz:[NSString stringWithFormat:@"/some/path/to/baz/%@", bazId]]];
    }];
  }];
}

-(Baz *)bazWithPathToBaz:(NSString *)bazPath {
  return [TyphoonDefinition withClass:[Baz class] configuration:^(TyphoonDefinition* definition) {
    [definition useInitializer:@selector(initWithBazPath:) parameters:^(TyphoonMethod *initializer) {
      [initializer injectParameterWith:bazPath];
    }];
  }];
}

@end

调用时,传递给初始值设定项的路径为"/some/path/to/baz/<TyphoonInjectionByRuntimeArgument: 0x15ea4670, type=Undifined>"

1 个答案:

答案 0 :(得分:0)

您是如何获得Foo的构建实例的?上面的汇编代码看起来没问题,但请记住以下几点:

  • 构建时间:程序集返回TyphoonDefinition的实例。 Typhoon对此程序集进行检测,以收集在运行时返回构建实例所需的信息。这包括使用代理注入运行时参数(TyphoonInjectionByRuntimeArgument的实例)。
  • 运行时:程序集现在根据定义中定义的规则返回构建的组件。 (它实际上是指向TyphoonComponentFactory的代理)。

创建一个或多个程序集后,需要以下内容让程序集返回构建的组件:

- (void)testFoobar
{
    //Pass in a not-built assembly to TyphoonComponentFactory
    TyphoonComponentFactory *factory =
        [TyphoonBlockComponentFactory factoryWithAssemblies:@[[Assembly assembly]]]; 

    //Now we have a built assembly
    Assembly *builtAssembly = (Assembly*) factory;

    Foo *builtFoo = [builtAssembly fooWithFooId:@"1234" andBarId:@"5678"];
    NSLog(@"%@", builtFoo);
}

结果: <Foo: self.fooId=1234, self.bar=<Bar: self.barId=5678>>

(或者在应用程序的情况下,您可以使用plist-integration来引导Typhoon并注入app委托。请注意,您可以将程序集本身注入任何组件,作为TyphoonComponentFactory或冒充一个组件您可以从一个对象图(例如视图控制器)转换到另一个对象图。


修改

虽然这不是最初的意图,但在大多数情况下,您也可以在程序集中使用运行时参数,现在我们在自己的应用程序中执行此操作。例如:

- (OfferManager *)offerManager
{
    return [TyphoonDefinition withClass:[OfferManager class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition useInitializer:@selector(initWithEngine:) 
            parameters:^(TyphoonMethod *initializer) {

            [initializer injectParameterWith:
                [self engineWithPollingInterval:@120 cacheExpire:@3600]];
        }];
    }];
}

。 。但目前不可能创建一个顶级定义,这是另一个带有运行时参数的定义的结果。示例:

- (Engine*) preConfiguredEngine {
    return [self engineWithPollingInterval:@120 cacheExpire:@3600];
} 

。 。原因很简单,如果你需要这个,我们可以看一下。