Lightweight IOC framework SwiftSuspenders

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

The 1.6 version of the framework in the https://github.com/tschneidereit/SwiftSuspenders/blob/the-past/, is now in its 2 version re architecture, so I decided to study has 1.6 versions of mature, and have time to study the 2 version of the.


Basic knowledge of IOC

Inversion of control (Inversion of Control, the English abbreviation for IoC) is also called dependency injection (Dependency Injection, the English abbreviation is DI), is a way to reduce programming mode coupling degree, it will be through the process of creating objects are decoupled to reduce the dependency relationships among objects. Specifically, in this paper the dependency injection those things to explain in great detail, also can be the reference and deep understanding of the old dependency injection(Dependence Injection).


The describeType function introduction

SwiftSuspenders is to achieve its reflection mechanism by using the describeType function.

The describeType function can be used to generate the description of ActionScript objects (named as method parameters) of XML objects. Reflective programming concepts using this method can realize the ActionScript language.

In order to elaborate on the function, we first define a class MyClass:

    public class MyClass extends Object
    {
        public const const_varable:int = 0;
        [Inject(desc="a public varable")]
        public var pub_varable:String = "";private var pri_varable:String = "";
        [Inject(desc="a static function")]
        public static function static_func(s:String):void
        {
            trace(s);
        }
        public function get accpri():String
        {
            return pri_varable;
        }
        public function set accpri(v:String):void
        {
            pri_varable = v;
        }
        public function TraceOut():void {
            trace(accpri);
        }
        public function MyClass()
        { 
        }
    }

If the parameter passed is an instance of a type, the returned XML object includes all instances of the type of attribute, but does not include any static attribute.

var m:MyClass = new MyClass();

trace(describeType(m));

We can get the following XML:

<type name="MyClass" base="Object" isDynamic="false" isFinal="false" isStatic="false">
  <extendsClass type="Object"/>
  <constant name="const_varable" type="int">
    <metadata name="__go_to_definition_help">
      <arg key="pos" value="110"/>
    </metadata>
  </constant>
  <variable name="pub_varable" type="String">
    <metadata name="Inject">
      <arg key="desc" value="a public varable"/>
    </metadata>
    <metadata name="__go_to_definition_help">
      <arg key="pos" value="184"/>
    </metadata>
  </variable>
  <accessor name="accpri" access="readwrite" type="String" declaredBy="MyClass">
    <metadata name="__go_to_definition_help">
      <arg key="pos" value="425"/>
    </metadata>
    <metadata name="__go_to_definition_help">
      <arg key="pos" value="498"/>
    </metadata>
  </accessor>
  <method name="TraceOut" declaredBy="MyClass" returnType="void">
    <metadata name="__go_to_definition_help">
      <arg key="pos" value="571"/>
    </metadata>
  </method>
  <metadata name="__go_to_ctor_definition_help">
    <arg key="pos" value="632"/>
  </metadata>
  <metadata name="__go_to_definition_help">
    <arg key="pos" value="67"/>
  </metadata>
</type>

Ignore the __go_to_ctor_definition_help form of metadata, see the following XML:

<type name="MyClass" base="Object" isDynamic="false" isFinal="false" isStatic="false">
  <extendsClass type="Object"/>
  <constant name="const_varable" type="int">
  </constant>
  <variable name="pub_varable" type="String">
    <metadata name="Inject">
      <arg key="desc" value="a public varable"/>
    </metadata>
  </variable>
  <accessor name="accpri" access="readwrite" type="String" declaredBy="MyClass">
  </accessor>
  <method name="TraceOut" declaredBy="MyClass" returnType="void">
  </method>
</type>

1 incoming inspection of parsing XML object is the object or class, method is to check the <type> the isStatic attribute of the tag value, the value in the value parameter is an instance of a type of false.

No 2.private properties and methods are describeType function analysis to.

To obtain the static properties of a type, then transfer the type itself. The returned XML object includes not only static attribute types, but also including all the examples of its properties.

trace(describeType(MyClass));Ignore the __go_to_ctor_definition_help forms of metadata, XML can be obtained as follows:

<type name="MyClass" base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <method name="static_func" declaredBy="MyClass" returnType="void">
    <parameter index="1" type="String" optional="false"/>
    <metadata name="Inject">
      <arg key="desc" value="a static function"/>
    </metadata>
  </method>
  <factory type="MyClass">
    <extendsClass type="Object"/>
    <constant name="const_varable" type="int">
    </constant>
    <variable name="pub_varable" type="String">
      <metadata name="Inject">
        <arg key="desc" value="a public varable"/>
      </metadata>
    </variable>
    <accessor name="accpri" access="readwrite" type="String" declaredBy="MyClass">
    </accessor>
    <method name="TraceOut" declaredBy="MyClass" returnType="void">
    </method>
  </factory>
</type>

1 if the incoming parameters for the class, the instance attributes are nested in the name <factory> tag, and distinguish the static attribute. In this case, the <type> the isStatic attribute of the tag is true.

2 of all non static methods will be displayed in the <factory> tag, a static method is displayed in the <factory> label.

The following table describes the describeType () some tags and attributes of XML objects (all classes and interfaces are used in the fully qualified name of the returned format):

Attribute description of <type>   root tag of the XML object.   Name of the name ActionScript object data type.   Direct superclass defines the class of base ActionScript objects. If the ActionScript object is a class object, the value is Class.   IsDynamic if the ActionScript object class definition is dynamic, it is true; otherwise, false. If the ActionScript object is of class object, the value is true, because Class is a dynamic.   IsFinal if the ActionScript object class definition is the final class, is true; otherwise, false.   IsStatic if the ActionScript object is of class or object constructor, is true; otherwise, false. This property is called isStatic, the reason is: if this property is true, without any tags nested inside a factory tag is static. <extendsClass>   The ActionScript object class definition each super class has a separate extendsClass Tags.   The type ActionScript object defining the class extended super class name. <implementsInterface>   The ActionScript object definition of the class or any of its super class implements each of the interface has a single implementsInterface tag.   Names defined class implements the interface type of the ActionScript object. <accessor>   Accessor is a property of the getter and setter functions.   The name name access device.   The access property access. Possible values include readonly, writeonly and readwrite.   The type attribute data types.   The declaredBy contains getter or setter function associated with the class. <constant>   Constant is an attribute defined using the const statement.   The name name.   The data type of type. <constructor>   Display in the constructor parameters. <method>   Method is to function as part of a class definition statement.   The name name method.   DeclaredBy contains the method definition class.   ReturnType method return value data types. <parameter>   Each parameter method definition has a single parameter tag. This label is nested in the <method> tag.   Index a number, corresponding to the parameter list in the order they appear in the method. The value of the first parameter is 1.   The data type of the type parameter.   If the optional parameter is optional, is true; otherwise, false. <variable>   A variable is an attribute defined using the VaR statement.   The name name variables.   The type data type of the variable. <factory>   If the ActionScript object is of class or object constructor, all instance attributes and methods are nested on the label. If <type> the isStatic attribute of the tag is true, are not nested in the <factory> all the attributes and methods within the tag is static. Only in the ActionScript object is a class object or constructor, this label will appear. <metadata>   [] enclose the name tag   name tag. <arg>   Tag ( ) parameters including the name key parameters;.   The value of the value parameter.


 The compiler is running in debug conditions we can get metadata, but the release compiler condition ignores unknown metadata, at this time, need to add in flex SDK compiler parameters.

-keep-as3-metadata+=MyMetadata


Application and API

1 definition of dependence

Swiftsuspenders supports 3 types of dependency:

The value of A. binding, an injection request returns for a given object

mapValue(whenAskedFor : Class, useValue : Object, named : String = "")

Class B. binding, will inject a new request is returned as an example of a given class

mapClass(whenAskedFor : Class, instantiateClass : Class, named : String = "")

C. singleton bound, all into the request returns for the same shared instance, the instance is created the first request.

mapSingleton(whenAskedFor : Class, named : String = "")

public function mapSingletonOf(whenAskedFor : Class, useSingletonOf : Class, named : String = "")

In addition, Swiftsuspenders support through the use of mapRule to extend the dependency mapping

When a type is injected at multiple sites, and the need to use a different dependency injection, injection by specifying a way to differentiate into all.


2 definition of the injection point

The support for Swiftsuspenders injection in 4 locations:

The A. property (such as setter)

The B. variable

The C. method (support optional parameters)

The D. constructor (support optional parameters)


3 variables into the case

    public interface IClass 
    {
        function ClassInfo():String;
    }

    public class ClassA implements IClass
    {
        
        public function ClassA() 
        {
            
        }
        public function ClassInfo():String
        {
            return "Class A";
        }
    }

    public class ClassB  implements IClass
    {
        
        public function ClassB() 
        {
            
        }
        public function ClassInfo():String
        {
            return "Class B";
        }
    }

    public class MyClass
    {
        [Inject]
        public var iclass:IClass;
        
        public function MyClass() 
        {
            
        }
        public function TraceOut():void
        {
            trace(iclass.ClassInfo());
        }
        
    }

        var inj :Injector = new Injector();

        inj.mapClass(MyClass, MyClass);
        inj.mapClass(IClass, ClassA);
        var a:MyClass = inj.getInstance(MyClass);
        inj.unmap(IClass);
        inj.mapClass(IClass, ClassB);
        var b:MyClass = inj.getInstance(MyClass);
        a.TraceOut();
        b.TraceOut();

The 4 constructor injection cases

 When using the injection of constructor injection, metadata must be placed in front of the class definition, rather than in the constructor, this is because the Flash Player due to the limit of.

Only need to modify the above code in the MyClass class:

    [Inject]
    public class MyClass
    {    
        public var iclass:IClass;
        
        
        public function MyClass(c:IClass) 
        {
            iclass = c;
        }
        public function TraceOut():void
        {
            trace(iclass.ClassInfo());
        }
        
    }

5 other

A. PostConstruct can be used to mark the injection method calls automatically after the completion of the

Some need in the injection method call is completed, you can declare a [PostConstruct] metadata, resulting in the completion of all the injection, the calling method of [PostConstruct] stated. Can be determined by order method invocation order of the parameters, such as:

[PostConstruct(order=1)]


B. hasMapping can be used to query whether a dependence exists, if depend on the need to re mapping already exists, need to use unmap method to relieve the dependence.


C. support sub injector, achieved by createChildInjector method.


D. support into the information through the XML file configuration.


Design structure



The SwiftSuspenders class diagram as shown above. The framework uses Injector as the core. InjectionPoint package contains all into related categories, InjectionResult package contains the return policy related classes.

Injector m_mappings contains all the mapping between InjectionConfig, when calling mapClass, mapValue, mapSingleton is actually a mapping relationship, the sequence diagram as follows:



The InjecteeDescription object contains m_injecteeDescriptions, the object including all the injection point information, including the structure of the injection point injection point information, and other information. When getInstance mapping information according to the configuration to obtain all of the injection point, then according to the injection point injection to obtain the final object, the flow chart is as follows:

The describeType function inside the getInjectionPoints function is used before it is introduced to obtain the class content, and analyzed to obtain the injection point.




Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Camille at November 16, 2013 - 6:44 PM