今天闲来无事,为了做一个小功能,牵涉到数据的深度克隆,在折腾再三还是找到了一个最完美的方法(声明:代码都是引用的)。
第一次用的是byteArray+类注册做的,因为有复杂数据和vector和Array类型,最后克隆出来的数据类型丢失,代码如下:
- private static var aliasList:Array = [];
- /**
- * 复制一个对象
- * @param sourceObj 要复制的源对象
- * @param deep 是否对对象进行AMF序列化以后再深度复制
- * @return
- */
- public static function clone(sourceObj:*, deep:Boolean=true):*
- {
- if(!sourceObj)
- return null;
- var lastTime:Number = getTimer();
- if(deep)
- {
- // 得到 sourceObj的类名
- var qualifiedClassName:String = getQualifiedClassName(sourceObj);
- if(aliasList.indexOf(qualifiedClassName) == -1)
- {
- // e.g com.gdlib.test::RegisterClassAliasTest
- var packageName:String = qualifiedClassName.replace("::", ".");
- // 得到 sourceObj的类的类定义
- var classType:Class = getDefinitionByName(qualifiedClassName) as Class;
- // 注册此别名和类
- if(classType)
- {
- registerClassAlias(packageName, classType);
- aliasList.push(qualifiedClassName);
- trace("register class", packageName);
- }
- // 注册类公共属性(如果是复合类)
- registerVariables(sourceObj);
- }
- }
- // 复制此对象
- var b:ByteArray = new ByteArray();
- b.writeObject(sourceObj);
- b.position = 0;
- trace("Clone object takes", getTimer()-lastTime, "ms. ");
- return b.readObject();
- }
- /**
- * 注册某个类的公共属性(如果是复合类)所属的类的别名.
- * @param sourceObj
- */
- private static function registerVariables(sourceObj:*):void
- {
- // 注册类公共属性(如果是复合类)
- var xml:XML = describeType(sourceObj);
- var variable:XML;
- var variableType:String;
- var variablePackageName:String;
- var variableClassType:Class;
- var variableXml:XMLList;
- if(sourceObj is Class)
- variableXml = xml.factory.variable;
- else
- variableXml = xml.variable;
- // <variable name="point" type="flash.geom::Point">
- // <metadata name="__go_to_definition_help">
- // <arg key="pos" value="209"/>
- // </metadata>
- // </variable>
- // <variable name="name" type="String">
- // <metadata name="__go_to_definition_help">
- // <arg key="pos" value="142"/>
- // </metadata>
- // </variable>
- for each (variable in variableXml)
- {
- variableType = variable.@type;
- if(variableType.indexOf("::") != -1)
- {
- if(aliasList.indexOf(variableType) == -1)
- {
- // "flash.geom::Point" 转换为 "flash.geom.Point"
- variablePackageName = variableType.replace("::", ".");
- variableClassType = getDefinitionByName(variableType) as Class;
- // 注册此别名和类
- if(variableClassType)
- {
- registerClassAlias(variablePackageName, variableClassType);
- registerVariables(variableClassType);
- aliasList.push(variableType);
- trace("register variable", variablePackageName);
- }
- }
- }
- }
- }
于是乎,继续找结果找到了以下的方法:
首先,这个需要引用类库as3-commons-reflect(比较详细的解说可以看这:http://topmanopensource.iteye.com/blog/491080 下载类库地址:http://www.as3commons.org/as3-commons-reflect/)
/**
* 深度clone某个对象,包含Vector 和 Array
*/
public static function clone (_obj : * ): *
{
var returnCloneObj :*;
var objType : Type = Type . forInstance (_obj );
if (_obj is Vector .<*> || _obj is Array )
{
returnCloneObj = new objType . clazz ();
for each (var eachCloneObj :* in _obj )
{
returnCloneObj . push (cloneObj (eachCloneObj ));
}
}
else
{
returnCloneObj = cloneObj (_obj );
}
return returnCloneObj ;
}
/**
* clone 只能clone简单对象的所有的public属性
*/
private static function cloneObj (_obj : * ): *
{
var objType : Type = Type . forInstance (_obj );
var cloneObj :* = new objType . clazz ();
for each (var field : Field in objType . properties )
{
if (field is Variable || field is Accessor && Accessor (field ). writeable && field . name != 'prototype' )
{
cloneObj [ field . name ] = _obj [ field . name ];
}
}
return cloneObj ;
}
/**
* 深度clone某个对象,包含Vector 和 Array
*/
public static function clone (_obj : * ): *
{
var returnCloneObj :*;
var objType : Type = Type . forInstance (_obj );
if (_obj is Vector .<*> || _obj is Array )
{
returnCloneObj = new objType . clazz ();
for each (var eachCloneObj :* in _obj )
{
returnCloneObj . push (cloneObj (eachCloneObj ));
}
}
else
{
returnCloneObj = cloneObj (_obj );
}
return returnCloneObj ;
}
/**
* clone 只能clone简单对象的所有的public属性
*/
private static function cloneObj (_obj : * ): *
{
var objType : Type = Type . forInstance (_obj );
var cloneObj :* = new objType . clazz ();
for each (var field : Field in objType . properties )
{
if (field is Variable || field is Accessor && Accessor (field ). writeable && field . name != 'prototype' )
{
cloneObj [ field . name ] = _obj [ field . name ];
}
}
return cloneObj ;
}
终于可以万能的深度克隆各种数据了。