将ActionScript对象映射到类?

时间:2009-06-16 19:23:39

标签: flex actionscript-3

如果我有一堆普通的旧对象,那么将它们映射到一堆类的最佳方法是什么?

例如,如果我使用HTTPService引入一些JSON,然后反序列化它,我会有一堆看起来像这样的对象:

{ type: "person",
  id: 42,
  name: "David" }

我想把它们变成Person类的实例:

class Person {
    id:int;
    name:String;
}

有没有一些标准的,一般的方法呢?

(还要考虑:如何处理对象之间的关系?例如,如果Person有一个额外的“配偶”字段:

{ type: "person", spouse: 61, ... } // Where 61 is the ID of the spouse

谢谢, 大卫

2 个答案:

答案 0 :(得分:3)

没有标准的方法可以做到这一点,但你可以用两种不同的方式解决它。

版本1:构造方法

public class Person {
 public function Person(raw:Object=null) {
  if (raw != null) {
   for ( var key:String in raw ) {
    try {
     this[key] = raw[key];
    } catch (e:Error) {}
   }
   ...

这有点容易出错。如果名为 key 的属性不存在,则分配将失败,如果类型不匹配或无法自动强制,它也将失败。

版本2:flash.utils.describeType()

更复杂,让您更有控制力。首先,您必须创建Person的实例并调用describeType()。

var o:Object = { ... } // raw person data
var p:Person = new Person();
var typeDesc:XML = flash.utils.describeType( p );
for (var key:String in o) {
 var node:XML = typeDesc.variable.(@name==key)[0];
 if ( node != null ) {
  // Person class has a property *key*
  p[key] = o[key];
 }
}

但请注意使用getter和setter而不是公共变量。您无法使用typeDesc.variable访问它们,而是必须使用typeDesc.accessor并检查其访问属性是否不是writeonly。

关于您的类型键。要动态加载类,您可以执行以下操作:

var clazz:Class = flash.utils.getDefinitionByName(raw.type+"");
var person:Person = Person( new clazz() );

当然raw.type可能包含 Person com.package.Person ,只要您的目标类存在并且正在使用项目编译或使用SWC动态加载

看看:

http://livedocs.adobe.com/flex/3/langref/flash/utils/package.html#getDefinitionByName()http://livedocs.adobe.com/flex/3/langref/flash/utils/package.html#describeType()

希望这会有所帮助:)

答案 1 :(得分:1)

为了保持干净并且不易出错,我会使用单独的对象来完成这两项任务。例如,要处理转换,您可能具有以下对象:

public class PersonFactory 
{
    function buildFromGenerics(objects:Array):Array
    {
        var a:Array = [];
        var l:int = objects.length;

        for (var i:int = 0; i < l; i++) 
        {
            var o:Object = objects[i];
            var p:Person = new Person();
            p.id = o['id'];
            p.name = o['name'];
            a[i] = p
        }

        return a;
    }
}

将此步骤的所有逻辑移动到一个单独的对象中允许您隔离此功能,该功能实际上与实际的Person对象无关,因此没有任何可用性。

对于第二种情况,我会使用一个单独的对象来保存所有Person对象,并提供一个用于检索它们的接口,如下所示:

public class PersonCollection
{
    private var _people:Array;

    public function setPeople(people:Array):void
    {
        _people = people;
    }

    public function getPersonByID(id:int):Person
    {
        var l:int = _people.length;

        for (var i:int = 0; i < l; i++) 
        {
            var p:Person = _people[i];

            if (p.id == id)
            {
                return p;
            }
        }

        return null;
    }
}

这种分离有助于保持代码清洁,还提供了一种简单的方法来处理和管理代码。希望有所帮助。

相关问题