-
Notifications
You must be signed in to change notification settings - Fork 268
1.x_Assembling Components in XML
Block Assembly | Xml Assembly | Autowiring | Using-assembled-components | Installing | Configuration-Management-&-Testing
If you're familiar with the Spring Framework - the popular Dependency Injection Framework for Java, .NET and ActionScript, then the XML-style of assembly will feel very familiar. As yet, the XML-style doesn't provide as deep IDE integration as the block-style, which is why the block-style remains the recommended approach.
Basic code-completion is provided, initially with an XML schema. This works in AppCode, but the Xcode XML editor doesn't resolve schemas, it seems. To get the code completion, declare the XML-schema, like so:
<assembly xmlns="http://www.typhoonframework.org/schema/assembly"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.typhoonframework.org/schema/assembly
http://www.typhoonframework.org/schema/assembly.xsd">
You can declare a component that has another component injected via a property setter. The container will look up the component matching the required key. This feature is useful when you want to have multiple implementations of a protocol.
<component class="Knight" key="knight">
<property name="quest" ref="quest"/>
</component>
### Properties injected by value:
Properties can be injected by value. The container will look up the required class or primitive type. It's easy to register your own additional converters.
This makes it possible to have components configured for eg "Test" vs. "Production" scenarios and provides a good compromise between pure unit testing and integration testing.
<component class="Knight" key="knight">
<property name="damselsRescued" value="12"/>
<property name="imageUrl" value="http://www.appsquick.ly/theQuest.jpg"/>
</component>
A property of type NSSet or NSArray can be populated as follows:
<property name="menuItems">
<collection>
<!-- Populate the property with components matching the 'ref' name -->
<ref>menuItemMyTrips</ref>
<ref>menuItemContact</ref>
<!-- Use Typhoon's type converter system to convert the string representation -->
<value requiredType="NSString">mary</value>
<value requiredType="NSNumber">12</value>
</collection>
</property>
### Property injection call-backs:
The container provides a way to invoke a method before or after property injection, to ensure that the instance is in the required state before receiving collaborating classes.
For example, in the case of a RootViewController, you can assert that root controller's view is not nil, before injecting child view controllers.
<component class="CampaignQuest" before-property-injection="questBeforePropertyInjection"
after-property-injection="questAfterPropertyInjection"/>
As an alternative to declaring the property injection methods in the assembly, if you're not worried about your class having a direct dependency on Typhoon, you can also implement the following protocol:
@protocol TyphoonPropertyInjectionDelegate <NSObject>
Sometimes you wish to define components that depend on each other. For example a ViewController that is injected with a view, and a View that is injected with the ViewController as a delegate.
This is possible using property-style injection, but not for initializer injection.
Besides property injection, initializer injection is supported.
Note that for initializer injection, if you want to supply values you must supply the required class, unless the type is a primitive (because the objective-C runtime doesn't supply type introspection on method parameters).
<component class="CavalryMan" key="anotherKnight">
<initializer selector="initWithQuest:">
<argument parameterName="quest" ref="quest"/>
<argument parameterName="hasHorseWillTravel" value="12"/>
<argument parameterName="imageUrl" value="http://www.appsquick.ly" required-class="NSURL" />
</initializer>
</component>
Initializer injection can be used for both alloc'd and auto-release/class style methods. As long as the method follows normal naming conventions, the container will guess weather it's a class method or alloc init'd method. This can be over-ridden with the 'is-class-method' attribute. The default value is 'guess'. Acceptable values are: {'guess', 'yes/true', 'no/false'}.
<component class="NSURL" key="serviceUrl">
<initializer selector="URLWithString:" is-class-method="yes">
<argument parameterName="string" value="http://dev.foobar.com/service/" required-class="NSString"/>
</initializer>
</component>
Sometimes you have a component, such as one from a 3rd party library that produces a configurable instance that you'd like to inject as a dependency in other components. You can do this using a factory component:
<component class="SwordFactory" key="swordFactory"/>
<component class="Sword" key="blueSword" factory-component="swordFactory">
<initializer selector="swordWithSpecification:">
<argument parameterName="specification" value="blue" required-class="NSString"/>
</initializer>
</component>
- The default scope is 'TyphoonScopeObjectGraph' - a scope that is (as far as we know) unique among DI containers. This scope is especially geared towards mobile and desktop applications. When a component is resolved, any dependencies with the object-graph will be treated as shared instances during resolution. Once resolution is complete they are not retained by the TyphoonComponentFactory. This allows instantiating an entire object graph for a use-case (say for a ViewController), and then discarding it when that use-case has completed.
- The prototype scope means that a new instance will always be created by Typhoon.
- The singleton scope means that Typhoon will retain the instance that exists for as long as the TyphoonComponentFactory exists.
- The weakSingleton scope works the same as singleton, except that not components are currently using the singleton, it will be destroyed. A subsequent request will have it created again.
<component class="Knight" key="knight" scope="singleton">
<property name="quest" ref="quest"/>
</component>
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.