Permalink
Browse files

Added support for adding and removing modules by returning a new

injector. Closes pull request #30
  • Loading branch information...
1 parent 0008465 commit 56276ad960cdfd938e9a1224f76931615dcd9b67 @thestoics thestoics committed Nov 30, 2012
@@ -243,6 +243,8 @@
4BA6DD1F12AAB3CD00CFFD70 /* JSObjectionInjectorEntry.h in Copy Header Files */ = {isa = PBXBuildFile; fileRef = 4BED512F12AA8BF300CA6B36 /* JSObjectionInjectorEntry.h */; };
4BA6DD2012AAB3CD00CFFD70 /* JSObjectionInjector.h in Copy Header Files */ = {isa = PBXBuildFile; fileRef = 4BED513012AA8BF300CA6B36 /* JSObjectionInjector.h */; };
4BA6DD2112AAB3CD00CFFD70 /* JSObjectionBindingEntry.h in Copy Header Files */ = {isa = PBXBuildFile; fileRef = 4BED513112AA8BF300CA6B36 /* JSObjectionBindingEntry.h */; };
+ 4BB07D751668679A00D9BA1E /* AddAndRemoveModulesSpecs.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB07D741668679A00D9BA1E /* AddAndRemoveModulesSpecs.m */; };
+ 4BB07D761668679A00D9BA1E /* AddAndRemoveModulesSpecs.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB07D741668679A00D9BA1E /* AddAndRemoveModulesSpecs.m */; };
4BE78760145647EF00BD705E /* JSObjectFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BE7875E145647EF00BD705E /* JSObjectFactory.h */; };
4BE78761145647EF00BD705E /* JSObjectFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BE7875E145647EF00BD705E /* JSObjectFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
4BE78762145647EF00BD705E /* JSObjectFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE7875F145647EF00BD705E /* JSObjectFactory.m */; };
@@ -480,6 +482,7 @@
4B9D310213DF613500C81C45 /* JSObjection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSObjection.m; sourceTree = "<group>"; };
4BA9CFEB12AA86D300674F0E /* OCHamcrest-iPhone.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "OCHamcrest-iPhone.framework"; path = "Vendor/OCHamcrest-iPhone.framework"; sourceTree = "<group>"; };
4BA9CFF412AA86E600674F0E /* OCHamcrest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCHamcrest.framework; path = Vendor/OCHamcrest.framework; sourceTree = "<group>"; };
+ 4BB07D741668679A00D9BA1E /* AddAndRemoveModulesSpecs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddAndRemoveModulesSpecs.m; sourceTree = "<group>"; };
4BE7875E145647EF00BD705E /* JSObjectFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectFactory.h; sourceTree = "<group>"; };
4BE7875F145647EF00BD705E /* JSObjectFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSObjectFactory.m; sourceTree = "<group>"; };
4BED511612AA8B7A00CA6B36 /* Objection.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Objection.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -823,16 +826,17 @@
4BF45123129197F3006EB2D5 /* Specs */ = {
isa = PBXGroup;
children = (
- D2AAC07E0554694100DB5192 /* CircularDependencySpecs.m */,
4B42587C13F56EA3006BC001 /* Specs-OSX */,
4B42580C13F56CC0006BC001 /* Specs-iOS */,
4B42571213F5665C006BC001 /* Kiwi */,
4BF452461291AFEA006EB2D5 /* Helpers */,
+ D2AAC07E0554694100DB5192 /* CircularDependencySpecs.m */,
4BF4516B129199AF006EB2D5 /* BasicUsageSpecs.m */,
4BF451E21291AD28006EB2D5 /* InjectionErrorsSpecs.m */,
4B7300D712AA8F3400903427 /* InheritanceSpecs.m */,
4B95819612AE593F00CBF1EB /* ModuleUsageSpecs.m */,
4B4289301567F3EC004F73D3 /* InitializerSpecs.m */,
+ 4BB07D741668679A00D9BA1E /* AddAndRemoveModulesSpecs.m */,
);
path = Specs;
sourceTree = "<group>";
@@ -1179,6 +1183,7 @@
D2AAC07E0554694100DB5196 /* CircularDependencyFixtures.m in Sources */,
4B4289311567F3EC004F73D3 /* InitializerSpecs.m in Sources */,
4B428935156806E6004F73D3 /* InitializerFixtures.m in Sources */,
+ 4BB07D751668679A00D9BA1E /* AddAndRemoveModulesSpecs.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1275,6 +1280,7 @@
D2AAC07E0554694100DB5197 /* CircularDependencyFixtures.m in Sources */,
4B4289321567F3EC004F73D3 /* InitializerSpecs.m in Sources */,
4B428936156806E6004F73D3 /* InitializerFixtures.m in Sources */,
+ 4BB07D761668679A00D9BA1E /* AddAndRemoveModulesSpecs.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2,16 +2,23 @@
#import "JSObjectionModule.h"
@interface JSObjectionInjector : NSObject {
- NSDictionary *_globalContext;
- NSMutableDictionary *_context;
- NSSet *_eagerSingletons;
+ NSDictionary *_globalContext;
+ NSMutableDictionary *_context;
+ NSSet *_eagerSingletons;
+ NSMutableArray *_modules;
}
- (id)initWithContext:(NSDictionary *)theGlobalContext;
- (id)initWithContext:(NSDictionary *)theGlobalContext andModule:(JSObjectionModule *)theModule;
-- (id)initWithContext:(NSDictionary *)theGlobalContext andModules:(NSArray *)modules;
+- (id)initWithContext:(NSDictionary *)theGlobalContext andModules:(NSArray *)theModules;
- (id)getObject:(id)classOrProtocol;
- (id)getObjectWithArgs:(id)classOrProtocol, ... NS_REQUIRES_NIL_TERMINATION;
- (id)getObject:(id)classOrProtocol arguments:(va_list)argList;
+- (id)withModule:(JSObjectionModule *)theModule;
+- (id)withModules:(JSObjectionModule *)first, ... NS_REQUIRES_NIL_TERMINATION;
+- (id)withModuleCollection:(NSArray *)theModules;
+- (id)withoutModuleOfType:(Class)moduleClass;
+- (id)withoutModuleOfTypes:(Class)first, ... NS_REQUIRES_NIL_TERMINATION;
+- (id)withoutModuleCollection:(NSArray *)moduleClasses;
- (id)objectForKeyedSubscript: (id)key;
@end
@@ -43,6 +43,7 @@ - (id)initWithContext:(NSDictionary *)theGlobalContext {
if ((self = [super init])) {
_globalContext = [theGlobalContext retain];
_context = [[NSMutableDictionary alloc] init];
+ _modules = [[NSMutableArray alloc] init];
[self configureDefaultModule];
[self initializeEagerSingletons];
}
@@ -58,9 +59,9 @@ - (id)initWithContext:(NSDictionary *)theGlobalContext andModule:(JSObjectionMod
return self;
}
-- (id)initWithContext:(NSDictionary *)theGlobalContext andModules:(NSArray *)modules {
+- (id)initWithContext:(NSDictionary *)theGlobalContext andModules:(NSArray *)theModules {
if ((self = [self initWithContext:theGlobalContext])) {
- for (JSObjectionModule *module in modules) {
+ for (JSObjectionModule *module in theModules) {
[self configureModule:module];
}
[self initializeEagerSingletons];
@@ -123,6 +124,66 @@ - (id)getObject:(id)classOrProtocol arguments:(va_list)argList {
}
+- (id)withModule:(JSObjectionModule *)theModule {
+ return [self withModuleCollection:[NSArray arrayWithObject:theModule]];
+}
+
+- (id)withModules:(JSObjectionModule *)first, ... {
+ va_list va_modules;
+ NSMutableArray *modules = [NSMutableArray arrayWithObject:first];
+ va_start(va_modules, first);
+
+ JSObjectionModule *module;
+ while ((module = va_arg( va_modules, JSObjectionModule *) )) {
+ [modules addObject:module];
+ }
+
+ va_end(va_modules);
+ return [self withModuleCollection:modules];
+
+}
+
+- (id)withModuleCollection:(NSArray *)theModules {
+ NSMutableArray *mergedModules = [NSMutableArray arrayWithArray:_modules];
+ [mergedModules addObjectsFromArray:theModules];
+ return [[[self class] alloc] initWithContext:_globalContext andModules:mergedModules];
+}
+
+- (id)withoutModuleOfType:(Class)moduleClass {
+ return [self withoutModuleCollection:[NSArray arrayWithObject:moduleClass]];
+}
+
+- (id)withoutModuleOfTypes:(Class)first, ... {
+ va_list va_modules;
+ NSMutableArray *classes = [NSMutableArray arrayWithObject:first];
+ va_start(va_modules, first);
+
+ Class aClass;
+ while ((aClass = va_arg( va_modules, Class) )) {
+ [classes addObject:aClass];
+ }
+
+ va_end(va_modules);
+ return [self withoutModuleCollection:classes];
+
+}
+
+- (id)withoutModuleCollection:(NSArray *)moduleClasses {
+ NSMutableArray *remainingModules = [NSMutableArray arrayWithArray:_modules];
+ NSMutableArray *withDefaultModule = [NSMutableArray arrayWithArray:moduleClasses];
+ [withDefaultModule addObject:[__JSObjectionInjectorDefaultModule class]];
+ for (JSObjectionModule *module in _modules) {
+ for (Class moduleClass in withDefaultModule) {
+ if([module isKindOfClass:moduleClass]) {
+ [remainingModules removeObject:module];
+ }
+ }
+ }
+ NSLog(@"Hello: %@", remainingModules);
+ return [[[self class] alloc] initWithContext:_globalContext andModules:remainingModules];
+}
+
+
#pragma mark - Private
@@ -140,6 +201,7 @@ - (void)initializeEagerSingletons {
}
- (void)configureModule:(JSObjectionModule *)module {
+ [_modules addObject:module];
[module configure];
NSSet *mergedSet = [module.eagerSingletons setByAddingObjectsFromSet:_eagerSingletons];
[_eagerSingletons release];
@@ -0,0 +1,43 @@
+#import "SpecHelper.h"
+#import "Fixtures.h"
+#import "ModuleFixtures.h"
+
+
+SPEC_BEGIN(AddAndRemoveModulesSpecs)
+__block SecondModule *module = nil;
+__block JSObjectionInjector *injector = nil;
+
+beforeEach(^{
+ module = [[[SecondModule alloc] init] autorelease];
+ gEagerSingletonHook = NO;
+ injector = [JSObjection createInjector:module];
+});
+
+it(@"builds a new injector with new modules", ^{
+ assertThat([injector getObject:@protocol(GearBox)], is(instanceOf([AfterMarketGearBox class])));
+ assertThat([injector getObject:[Car class]], isNot(instanceOf([ManualCar class])));
+ assertThatBool(gEagerSingletonHook, equalToBool(NO));
+
+ injector = [injector withModules:
+ [[[ProviderModule alloc] init] autorelease],
+ [[[FirstModule alloc] init] autorelease], nil];
+
+ assertThat([injector getObject:@protocol(GearBox)], is(instanceOf([AfterMarketGearBox class])));
+ assertThat([injector getObject:[Car class]], is(instanceOf([ManualCar class])));
+ assertThatBool(gEagerSingletonHook, equalToBool(YES));
+});
+
+it(@"builds a new module without the module types", ^{
+ injector = [injector withModules:
+ [[[ProviderModule alloc] init] autorelease], nil];
+
+ assertThat([injector getObject:@protocol(GearBox)], is(instanceOf([AfterMarketGearBox class])));
+ assertThat([injector getObject:[Car class]], is(instanceOf([ManualCar class])));
+
+ injector = [injector withoutModuleOfTypes:[SecondModule class], [ProviderModule class], nil];
+
+ assertThat([injector getObject:@protocol(GearBox)], is(nilValue()));
+ assertThat([injector getObject:[Car class]], isNot(instanceOf([ManualCar class])));
+});
+
+SPEC_END
View
@@ -10,6 +10,7 @@
id<GearBox> gearBox = [[[AfterMarketGearBox alloc] init] autorelease];
module = [[[MyModule alloc] initWithEngine:engine andGearBox:gearBox] autorelease];
+ gEagerSingletonHook = NO;
JSObjectionInjector *injector = [JSObjection createInjector:module];
[JSObjection setDefaultInjector:injector];
});

0 comments on commit 56276ad

Please sign in to comment.