1
votes

Is it possible to have an assembly to define a base configuration and subclass it to have additional configurations?

I'm trying something like this:

@interface RootAssembly : TyphoonAssembly
- (id)abstractObject;
- (id)object;
@end


@implementation RootAssembly
- (id)abstractObject {
    return [TyphoonDefinition withClass:[NSObject class]];
}

- (id)object {
    return [TyphoonDefinition withParent:[self abstractObject] class:[NSObject class]];
}

@end


@interface ChildAssembly : RootAssembly @end

@implementation ChildAssembly
- (id)object {
    return [TyphoonDefinition withParent:[super abstractObject] class:[NSObject class]];
}
@end

Everything works fine if only one assembly is used. If also a second one is instantiated and activated, the method returning the object is not yet swizzled and tries to build a definition, resulting in an exception:

2015-05-27 18:44:37.542 Typho[17693:8488013] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Only TyphoonDefinition object can be set as parent. But in method '(null)' object of class NSObject set as parent'

see more here: https://gist.github.com/oettam/01ac812c040ed28d913c

Is this actually the way to go?

1

1 Answers

0
votes

You can define any sub-class of an assembly to act in place as the original, or even another class as long as it responds to the same messages. Similarly, if your collaborating assemblies are backed by a protocol, you can tell Typhoon what the realization of that is on startup.

Consider:

@interface ApplicationAssembly : TyphoonAssembly

//A collaborating assembly
@property(nonatomic, strong, readonly) KernelProvider *kernelProvider;

@end

@implementation ApplicationAssembly 

- (SomeViewController*)viewController 
{
    return [TyphoonDefinition withClass:[SomeViewController class] 
      configuration:^(TyphoonDefinition *definition) {

      [definition injectProperty:@selector(something) with:_kernelProvider.service];
    ];
}

As startup you can provide any realization of KernelProvider that you like.

ApplicationAssembly *assembly = [[ApplicationAssembly new] 
    activateWithCollaboratingAssemblies:@[TestKernelProvider new]];

In the output you'll see Typhoon log:

TestKernelProvider will act in place of [KernelProvider class];

The same applies to the plist integration style of bootstrapping Typhoon. Just declare the concrete realization of each assembly in the plist.

Is this the kind of thing you want to do? I'm not sure what's happening in the example above, but if you show me how you're bootstrapping Typhoon then I can look at it for you.