-
Notifications
You must be signed in to change notification settings - Fork 268
TyphoonAssembly
"Any magic, sufficiently analyzed is indistinguishable from technology."
Clarke C. Arthur ;)
Here will take a look at how Typhoon assemblies are instrumented at run-time to allow the following feature:
- Before activation your assemblies return an instance of
TyphoonDefinition
- After activation an instance built according to the rules in the definition is returned.
#Assembly Instrumentation
Typhoon uses a programming paradigm called Aspect Oriented Programming (AOP) to instrument the methods of your assembly classes with additional behavior.
AOP is used to encapsulate "cross-cutting" concerns. These are the kind of requirements that "cut across" many modules in your system. In our case the requirement is:
Whenever a new definition is created it should be assigned
a unique key based on the method name that defined it.
AOP defines the following kinds of method interceptions:
Interception | Description |
---|---|
Before | Additional behavior is added before a method invocation. |
After | Additional behavior is added after a method invocation. |
After Throwing | Additional behavior is added after an exception occurs. |
Around | A flexible style that can be used to model any of the above. |
TyphoonAssembly
instrumentation uses the 'After' style - after a definition is returned it as allocated a unique key based on the method name that defined it.
##Registration into TyphoonComponentFactory
- After instrumentation each of the definitions in your assemblies - we can think of these as blue-prints for creating a an instance - are registered into a
TyphoonComponentFactory
- The
TyphoonComponentFactory
then runs its'TyphoonDefinitionPostProcessor
system to modify these recipes for creating an instance. Post processors can be plugged in to perform things like configuration.
#How is method interception achieved?
Method interception is achieved using the Objective-C run-time. Objective-C is a late binding language or in other words it uses messaging or dynamic dispatch to achieve method invocation. This provides the ability to forward method invocations to an alternative implementation, optionally calling the original, and is known as swizzling.
Swizzling comes in a few flavors:
Swizzle | Effect |
---|---|
Method swizzling | Forward invocations of a method for all instances of a given class, optionally calling the original, at some point. |
isa pointer swizzling | Forward invocations of a method for a specific instance of a given class, optionally calling the original, at some point. |
NB: Other languages that use static dispatch can achieve 'late binding' by virtue of having a virtual machine and class loader system, which provides an alternative hook point.
##A hack? Not at all
Swizzling has sometimes been described in informal discussion groups as a hack. Like any powerful technique it can be easily misused, however it in fact the foundation of many of Cocoa's most powerful features, including:
- Property Observers (KVO) : Property setter is intercepted to notify subscribers when a new value is supplied.
- Core Data Managed Objects
- etc
#A Cat, All Dressed Up as a Duck
- Before activation your assemblies return an instance of
TyphoonDefinition
- After activation an instance built according to the rules in the definition is returned.
To achieve that latter requirement, at runtime an instance of TyphoonComponentFactory
actually poses as your assembly class.
- When an Objective-C method is invoked for a given instance, a look-up table is consulted to resolve that method to a function pointer.
- When a method that does not exist for that class is invoked, before raising an error, the object is given the opportunity to forward the invocation to an alternative endpoint, again thanks to Objective-C's messaging system.
Invocations of TyphoonComponentFactory
methods are redirected to the method
-(id) componentForKey:(NSString*)key
. . using the unique key that was generated when instrumenting the assembly above.
(add diagram?)
#Benefits
We use a meta programming DSL to define dependency injection container with rules for assembling instances.
- No magic strings - use regular IDE refactoring tools for code-completion, method renaming, etc.
- Allows collaborating assemblies / modularization
- Allow more than one component of the same type by supporting explicit wiring as well as auto-wiring. (Objective-C is weak on auto-wiring in any case - type information is only returned for properties).
- Does not require any IDE plugins or special tool support.
Something still not clear? How about posting a question on StackOverflow.
Get started in two minutes.
Get familiar with Typhoon.
- Types of Injections
- What can be Injected
- Auto-injection (Objective-C)
- Scopes
- Storyboards
- TyphoonLoadedView
- Activating Assemblies
Become a Typhoon expert.
For contributors or curious folks.