2009-06-16 258 views
1

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

例如,如果我使用的HTTPService在一些JSON拉,然后反序列化,我有一堆看起来像对象:

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

而且我想他们变成的实例一个人类:

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

是否有一些标准的,一般的做法呢?

(也被认为是:怎么样处理对象之间的关系的一些标准的方式。例如,如果人有一个额外的“配偶”字段:?

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

谢谢, 大卫

+0

你使用AMF来接收你的数据吗? – Josh 2009-06-16 19:30:34

+0

否...如果我使用AMF,这会更容易,但其他事情(特别是服务器端代码)会变得更加复杂。 – 2009-06-17 17:52:17

回答

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) {} 
    } 
    ... 

这是一种容易出错的。如果名称为的键不存在,则分配将失败,如果类型不匹配或不能自动被强制转换,它也会失败。

版本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]; 
} 
} 

但要小心使用getters和setter而不是公共变量。你不能用typeDesc.variable来访问它们,而是你必须使用typeDesc.accessor并检查它的访问属性是不是writeonly。

关于您的类型键。加载类动态,你可以这样做:

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

中raw.type可能包含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()

希望这有助于:)

+0

是的,它的确如此 - 非常感谢。 – 2009-06-17 17:54:24

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; 
    } 
} 

这种分离有助于保持你的代码干净,并提供了一个简单的方法来处理和管理它。希望有所帮助。