아마 Flash를 오래 하신분들은 한번쯤 들어봤지만 지금은 다들 잊고 계실만한 메소드가 있습니다.

바로 flash.utils.describeType 이라는 클래스인데요.

객체를 넘겨주면 그 객체의 정보를 자세하게 파악해서 XML로 돌려주는 메소드입니다.

"어따 쓸까"하고 묻어뒀던 메소드인데

오늘 의외의 쓰임새를 알아냈습니다.



먼저 몸을 먼저 풀어보죠.

var mcClass: Class = Object( mc ).constructor;

trace( mcClass ); // [class MovieClip]

var mc2: MovieClip = new mcClass();

trace( mc2 ); // [object MovieClip]

이라는 코드가 있습니다.

mc라는 instance에서 flash.display.MovieCilp 이라는 Class를 가져오는 방법은 뭘까요?

var mcClass: Class = Object( mc ).constructor;

trace( mcClass ); // [class MovieClip]

var mc2: MovieClip = new mcClass();

trace( mc2 ); // [object MovieClip]

위와 같이 할 수 있겠죠.

이 방법이 instance로부터 class를 가져오는 방법입니다.



하지만 이것도 가능할까요?

먼저 A라는 class가 있습니다.

package
{
     import flash.display.MovieClip;

     public class A
     {
          public var mc: MovieClip = null;

          public function A()
          {

          }
     }
}

이 A라는 class에는 mc 라는 property가 있습니다.

만약 A.mc 가 객체로 들어있는 상태라면 문제가 없겠지만

아직 선언을 하지 않은 상태라면 mc는 현재 값이 null이라서

constructor를 가져올 수 없는 상태입니다.

이때는 어떻게 해야할까요?

이때 쓸 수 있는게 바로 describeType() 메소드입니다.

파라미터로 넘겨진 class나 instance의 구조를 샅샅히 뒤져줍니다.



테스트를 한번 해볼까요?

위에서 만든 A라는 class를 한번 돌려보겠습니다.

trace( describeType( A ).toXMLString() );


직접 해보실분들은 describeType( MovieClip ) 해주셔도 됩니다.

결과는 다음과 같죠.

<type name="A" base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="A">
    <extendsClass type="Object"/>
    <variable name="mc" type="flash.display::MovieClip"/>
  </factory>
</type>

장난 아니죠.

클래스를 샅샅히 살펴줍니다.

여기에 보면 <factory> 노드가 바로 class의 내용입니다.

여기에 보면 <variable> 이라는 노드가 보이죠.

여기에 @type을 보면 이쁘게 적혀있습니다.

이것을 응용하면 됩니다.



하지만 중요한게 property는 <variable> 노드로 나오지만

getter의 경우는 <accessor> 노드로 나옵니다.

여기서 끝이 아닙니다.

class의 경우는 <factory> 노드로 되어 있지만

instance의 경우에는 그렇지 않습니다.



간단하게 A 라는 class를 넘긴다고 가정하고 예제를 만들어보자면

다음과 같습니다.

trace( describeType( A ).factory.variable.( @name == "mc" ).@type.toString() );

복잡하지요?

풀어보자면 이렇습니다.

trace( describeType( A ).
factory. // factory 노드중에
variable. // variable 노드중에
( @name == "mc" ). // attribute가 "mc"인 녀석의
@type.toString() ); // "type" 이라는 attribute 값을 toString()

입니다.

이 기능을 메소드화 시키려면

class인지 instance인지 구분해야하고

accessor인지 variable인지 구분해야합니다.

이 모든걸 적용해서 메소드를 만들면 다음과 같습니다.

package
{
     import flash.utils.describeType;
     import flash.system.ApplicationDomain;

     public function getClassOfProperty( $instance: *, $propertyName: String ): Class
     {
          var describedXML: XML = describeType( $instance );

          if( $instance is Class )
               describedXML = describeType( $instance ).factory[ 0 ];

          var propertyClassName: String = describedXML.variable.( @name == $propertyName ).@type.toString().replace( "::", "." );

          if( propertyClassName == null )
               propertyClassName = describeType( $instance ).accessor.( @name == $propertyName ).@type.toString().replace( "::", "." );

          var propertyClass: Class = Class( ApplicationDomain.currentDomain.getDefinition( propertyClassName ) );

          return propertyClass;
     }
}


좀 복잡하지만 결과는 깔끔하게 class로 뽑아줍니다.



예제와 소스 첨부합니다.

getClassOfProperty 유틸 [ 다운 받기 ]





For the Better.

+ Recent posts