简体   繁体   中英

Reuse assembly in other assemblies

I'm trying to integrate typhoon into my project.

I have three classes, DBManager, ProductDataManager, and CustomerDataManager. Both ProductDataManager and CustomerDataManager depend on DBManager for db operation.

@interface ProductDataManager ()
@property (nonatomic, strong) DBManager *dbManager;
@end

@implementation ProductDataManager

- (instancetype)initWithDBManager:(DBManager*)dbManager
{
    self = [super init];
    if (self) {
        _dbManager = dbManager;
    }
    return self;
}


@interface CustomerDataManager ()
@property (nonatomic, strong) DBManager *dbManager;
@end

@implementation CustomerDataManager

- (instancetype)initWithDBManager:(DBManager*)dbManager
{
    self = [super init];
    if (self) {
        _dbManager = dbManager;
    }
    return self;
}

Now I create three assemblies for them.

@interface DBManagerAssembly ()

@end

@implementation DBManagerAssembly

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






@interface CustomerDataManagerAssembly ()
@property (nonatomic, strong) DBManagerAssembly *dbManagerAssembly;
@end

@implementation CustomerDataManagerAssembly

- (CustomerDataManager *)customerDataManager {
    return [TyphoonDefinition withClass:[CustomerDataManager class] configuration:^(TyphoonDefinition *definition) {
        [definition useInitializer:@selector(initWithDBManager:) parameters:^(TyphoonMethod *initializer) {
            [initializer injectParameterWith:self.dbManager];
        }];
    }];
}

- (DBManager *)dbManager {
    return [self.dbManagerAssembly dbManager];
}





@interface ProductDataManagerAssembly ()
@property (nonatomic, strong) DBManagerAssembly *dbManagerAssembly;
@end

@implementation ProductDataManagerAssembly

- (ProductDataManager *)productDataManager {
    return [TyphoonDefinition withClass:[ProductDataManager class] configuration:^(TyphoonDefinition *definition) {
        [definition useInitializer:@selector(initWithDBManager:) parameters:^(TyphoonMethod *initializer) {
            [initializer injectParameterWith:self.dbManager];
        }];
    }];
}

- (DBManager *)dbManager {
    return [self.dbManagerAssembly dbManager];
}

Activate them in AppDelegate

- (NSArray *)initialAssemblies
{
    return @[[DBManagerAssembly class], [ProductDataManagerAssembly class], [CustomerDataManagerAssembly class]];
}

But on app startup, it throws an exception

[NSException raise:NSInvalidArgumentException format:@"Key '%@' is already registered.", _definition.key];

My question is... how to reuse assembly properly and avoid exception?

Typhoon allows you to create logical groupings of the key architectural actors in your system. This feature is called Assembly Modularization . All of the components defined go into a single TyphoonComponentFactory - which contains recipes for emitting built instances.

组装模块

Before activation the assembly returns definitions. At runtime you can use the assembly as a facade to return built instances. It uses Objective-C message forwarding to resolve method calls to [factory componentForKey:theMethodName] . Therefore:

  • Each component in the entire set of assemblies must have a unique name.

In your code, you've defined:

- (DBManager *)dbManager {
    return [self.dbManagerAssembly dbManager];
}

Remove this definition, and edit customerDataManager to instead have:

[initializer injectParameterWith:[self.dbManagerAssembly dbManager]];

All will be well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM