Skip to content

Commit

Permalink
Returned instances are injected the component factory.
Browse files Browse the repository at this point in the history
Types conforming TyphoonComponentFactoryAware passed as the return type for a
factory generated from TyphoonFactoryProvider, will be now correctly injected
with the component factory.

This commit only works when using withProtocol:dependencies:returns:. Others
will come in later commits.

See appsquickly#144
  • Loading branch information
drodriguez committed Jan 31, 2014
1 parent 9cee525 commit 2704341
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@

- (TyphoonDefinition*)definitionForType:(id)classOrProtocol;

- (void)injectAssemblyOnInstanceIfTyphoonAware:(id)instance;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,15 @@ - (NSInvocation*)defaultInvocationToInit:(id)instance
return invocation;
}

- (void)injectAssemblyOnInstanceIfTyphoonAware:(id)instance;
- (void)injectAssemblyOnInstanceIfTyphoonAware:(id)instance
{
if ([instance conformsToProtocol:@protocol(TyphoonComponentFactoryAware)])
{
[self injectAssemblyOnInstance:instance];
}
}

- (void)injectAssemblyOnInstance:(id <TyphoonComponentFactoryAware>)instance;
- (void)injectAssemblyOnInstance:(id <TyphoonComponentFactoryAware>)instance
{
[instance setFactory:self];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <objc/runtime.h>

#import "TyphoonAssistedFactoryMethodClosure.h"
#import "TyphoonComponentFactory+InstanceBuilder.h"

static const void *sFactoryMethodClosures = &sFactoryMethodClosures;

Expand Down Expand Up @@ -83,6 +84,9 @@ - (void)forwardInvocation:(NSInvocation *)anInvocation
NSUInteger methodReturnLength = [closure.methodSignature methodReturnLength];
void *returnValue = malloc(methodReturnLength);
[closureInvocation getReturnValue:returnValue];

[self.componentFactory injectAssemblyOnInstanceIfTyphoonAware:*(__unsafe_unretained id *)returnValue];

[anInvocation setReturnValue:returnValue];
free(returnValue);
}
Expand Down
9 changes: 8 additions & 1 deletion Source/Factory/Provider/TyphoonAssistedFactoryBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,20 @@

#import <Foundation/Foundation.h>

#import "TyphoonComponentFactoryAware.h"
#import "TyphoonPropertyInjectionInternalDelegate.h"

/**
* Internal base class for all Typhoon assisted factories. Users should not use
* this class directly.
*/
@interface TyphoonAssistedFactoryBase : NSObject <TyphoonPropertyInjectionInternalDelegate>
@interface TyphoonAssistedFactoryBase : NSObject <TyphoonComponentFactoryAware, TyphoonPropertyInjectionInternalDelegate>

/**
* Part of TyphoonComponentFactoryAware. Renamed to componentFactory to not
* have code like factory.factory at some point.
*/
@property (nonatomic, strong, setter = setFactory:) id componentFactory;

/** Used internally by the getters of the properties in the subclasses */
- (id)injectionValueForProperty:(NSString *)property;
Expand Down
4 changes: 3 additions & 1 deletion Tests/Factory/Provider/Payment.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

#import <Foundation/Foundation.h>

@protocol Payment <NSObject>
#import "Typhoon.h"

@protocol Payment <TyphoonComponentFactoryAware, NSObject>

@property (nonatomic, strong, readonly) id<CreditService> creditService;
@property (nonatomic, strong, readonly) id<AuthService> authService;
Expand Down
2 changes: 2 additions & 0 deletions Tests/Factory/Provider/PaymentImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

@interface PaymentImpl : NSObject <Payment>

@property (nonatomic, strong) id factory;

- (instancetype)initWithCreditService:(id<CreditService>)creditService
authService:(id<AuthService>)authService
startDate:(NSDate *)startDate
Expand Down
9 changes: 9 additions & 0 deletions Tests/Factory/Provider/TyphoonAssistedFactoryBaseTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#import "TyphoonAssistedFactoryBase.h"

#import "TyphoonAbstractInjectedProperty.h"
#import "TyphoonComponentFactory.h"

@interface TyphoonAssistedFactoryBaseTest : SenTestCase
@end
Expand Down Expand Up @@ -53,4 +54,12 @@ - (void)test_should_respond_to_setDummySetter
assertThatBool([assistedFactory respondsToSelector:@selector(_setDummySetter:)], is(equalToBool(YES)));
}

- (void)test_should_conform_to_TyphoonComponentFactoryAware
{
id mockFactory = mock([TyphoonComponentFactory class]);

[assistedFactory setFactory:mockFactory];
assertThat(assistedFactory.componentFactory, is(equalTo(mockFactory)));
}

@end
71 changes: 71 additions & 0 deletions Tests/Factory/Provider/TyphoonFactoryProviderIntegrationTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
////////////////////////////////////////////////////////////////////////////////
//
// TYPHOON FRAMEWORK
// Copyright 2014, Jasper Blues & Contributors
// All Rights Reserved.
//
// NOTICE: The authors permit you to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////

#import "TyphoonFactoryProvider.h"

#import <SenTestingKit/SenTestingKit.h>

#import "AuthServiceImpl.h"
#import "CreditServiceImpl.h"
#import "PaymentFactory.h"
#import "PaymentFactoryAssembly.h"
#import "PaymentImpl.h"

@interface TyphoonFactoryProviderIntegrationTest : SenTestCase
@end

@implementation TyphoonFactoryProviderIntegrationTest
{
TyphoonBlockComponentFactory* componentFactory;
PaymentFactoryAssembly* assembly;
}

- (void)setUp
{
componentFactory = [[TyphoonBlockComponentFactory alloc] initWithAssembly:[PaymentFactoryAssembly assembly]];
assembly = (PaymentFactoryAssembly*) componentFactory;
}

- (void)test_dependencies_are_built_lazily
{
NSUInteger authServiceInstanceCounter = [AuthServiceImpl instanceCounter];
NSUInteger creditServiceInstanceCounter = [CreditServiceImpl instanceCounter];

id<PaymentFactory> factory = [assembly paymentFactory];

assertThatUnsignedInteger([AuthServiceImpl instanceCounter], is(equalToUnsignedInteger(authServiceInstanceCounter)));
assertThatUnsignedInteger([CreditServiceImpl instanceCounter], is(equalToUnsignedInteger(creditServiceInstanceCounter)));

// No need for the return value.
[factory paymentWithStartDate:[NSDate date] amount:123];

assertThatUnsignedInteger([AuthServiceImpl instanceCounter], is(equalToUnsignedInteger(authServiceInstanceCounter + 1)));
assertThatUnsignedInteger([CreditServiceImpl instanceCounter], is(equalToUnsignedInteger(creditServiceInstanceCounter + 1)));
}

- (void)test_assisted_factory_is_TyphoonComponentFactoryAware
{
NSObject<PaymentFactory>* factory = [assembly paymentFactory];

id cf = [factory valueForKey:@"componentFactory"];
assertThat(cf, is(equalTo(componentFactory)));
}

- (void)test_assisted_factory_injects_component_factory_in_object_instances
{
id<PaymentFactory> factory = [assembly paymentFactory];

PaymentImpl* payment = [factory paymentWithStartDate:[NSDate date] amount:456];

assertThat(payment.factory, is(equalTo(componentFactory)));
}

@end
20 changes: 0 additions & 20 deletions Tests/Factory/Provider/TyphoonFactoryProviderTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -137,24 +137,4 @@ - (void)test_initializer_factory_definition_should_have_injected_properties
assertThat(injectedPropertyNames, hasItems(equalTo(@"creditService"), equalTo(@"authService"), nil));
}

- (void)test_dependencies_are_built_lazily
{
NSUInteger authServiceInstanceCounter = [AuthServiceImpl instanceCounter];
NSUInteger creditServiceInstanceCounter = [CreditServiceImpl instanceCounter];

TyphoonBlockComponentFactory* componentFactory = [[TyphoonBlockComponentFactory alloc] initWithAssembly:[PaymentFactoryAssembly assembly]];
PaymentFactoryAssembly* assembly = (PaymentFactoryAssembly*) componentFactory;

id<PaymentFactory> factory = [assembly paymentFactory];

assertThatUnsignedInteger([AuthServiceImpl instanceCounter], is(equalToUnsignedInteger(authServiceInstanceCounter)));
assertThatUnsignedInteger([CreditServiceImpl instanceCounter], is(equalToUnsignedInteger(creditServiceInstanceCounter)));

// No need for the return value.
[factory paymentWithStartDate:[NSDate date] amount:123];

assertThatUnsignedInteger([AuthServiceImpl instanceCounter], is(equalToUnsignedInteger(authServiceInstanceCounter + 1)));
assertThatUnsignedInteger([CreditServiceImpl instanceCounter], is(equalToUnsignedInteger(creditServiceInstanceCounter + 1)));
}

@end
8 changes: 8 additions & 0 deletions Tests/Tests.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@
4EFAF61417E0D54700E93ACF /* CROPrototypeB.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EFAF61217E0D54700E93ACF /* CROPrototypeB.m */; };
4EFAF61517E0D54700E93ACF /* CROPrototypeB.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EFAF61217E0D54700E93ACF /* CROPrototypeB.m */; };
60A23DF66842404BA2052F31 /* libPods-iOS Tests (Cocoapods).a in Frameworks */ = {isa = PBXBuildFile; fileRef = B90D396911F743468FF96BB5 /* libPods-iOS Tests (Cocoapods).a */; };
6511E7E2189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6511E7E1189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m */; };
6511E7E3189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6511E7E1189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m */; };
6511E7E4189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6511E7E1189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m */; };
65123367189AD55300C21E63 /* PaymentFactoryAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = 65123366189AD55300C21E63 /* PaymentFactoryAssembly.m */; };
65123368189AD55300C21E63 /* PaymentFactoryAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = 65123366189AD55300C21E63 /* PaymentFactoryAssembly.m */; };
65123369189AD55300C21E63 /* PaymentFactoryAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = 65123366189AD55300C21E63 /* PaymentFactoryAssembly.m */; };
Expand Down Expand Up @@ -470,6 +473,7 @@
4EFAF60D17E0D50B00E93ACF /* CROPrototypeA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CROPrototypeA.m; sourceTree = "<group>"; };
4EFAF61117E0D54700E93ACF /* CROPrototypeB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CROPrototypeB.h; sourceTree = "<group>"; };
4EFAF61217E0D54700E93ACF /* CROPrototypeB.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CROPrototypeB.m; sourceTree = "<group>"; };
6511E7E1189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TyphoonFactoryProviderIntegrationTest.m; sourceTree = "<group>"; };
65123365189AD55300C21E63 /* PaymentFactoryAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PaymentFactoryAssembly.h; sourceTree = "<group>"; };
65123366189AD55300C21E63 /* PaymentFactoryAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PaymentFactoryAssembly.m; sourceTree = "<group>"; };
656A57611848DCB60081F72B /* TyphoonAssistedFactoryCreatorOneFactoryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TyphoonAssistedFactoryCreatorOneFactoryTest.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -942,6 +946,7 @@
children = (
657096941831464A00C10DA4 /* Fixtures */,
657096901831449000C10DA4 /* TyphoonFactoryProviderTest.m */,
6511E7E1189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m */,
656A57691848DD260081F72B /* TyphoonFactoryProviderTestHelper.h */,
656A57651848DD020081F72B /* TyphoonFactoryProviderTestHelper.m */,
656A57611848DCB60081F72B /* TyphoonAssistedFactoryCreatorOneFactoryTest.m */,
Expand Down Expand Up @@ -1412,6 +1417,7 @@
4B841519179B0EA600916BF5 /* SwordFactory.m in Sources */,
FA99165C18983621000AC4B5 /* TyphoonObjectDeallocCallbackTests.m in Sources */,
4B84151B179B0EA600916BF5 /* Knight.m in Sources */,
6511E7E2189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m in Sources */,
4B84152D179B0EA600916BF5 /* TyphoonPassthroughTypeConverterTests.m in Sources */,
4B84152F179B0EA600916BF5 /* TyphoonPrimitiveTypeConverterTests.m in Sources */,
46BD2236184F7481008E89E5 /* NSNullTypeConverter.m in Sources */,
Expand Down Expand Up @@ -1579,6 +1585,7 @@
BA798948941EE6E7B0746C60 /* MiddleAgesAssembly.m in Sources */,
BA7988B2B8BD792CF0A1F9A9 /* ObjectGraphAssembly.m in Sources */,
BA7982D26573611B9AE7E201 /* TyphoonScopeTests.m in Sources */,
6511E7E3189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m in Sources */,
BA7984BC277B2DAD4C374FD6 /* Fort.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -1615,6 +1622,7 @@
4BC648D917A20AD2007F0463 /* Sword.m in Sources */,
FA99165E18983703000AC4B5 /* TyphoonObjectDeallocCallbackTests.m in Sources */,
4BC648DA17A20AD2007F0463 /* SwordFactory.m in Sources */,
6511E7E4189C12D800DB8E8B /* TyphoonFactoryProviderIntegrationTest.m in Sources */,
4BC648DB17A20AD2007F0463 /* Knight.m in Sources */,
4BC648DC17A20AD2007F0463 /* TyphoonPassthroughTypeConverterTests.m in Sources */,
4BC648DD17A20AD2007F0463 /* TyphoonPrimitiveTypeConverterTests.m in Sources */,
Expand Down

0 comments on commit 2704341

Please sign in to comment.