상세 컨텐츠

본문 제목

[AS] 로드한 SWF 내부에 작성된 ActionScript 클래스 이름 찾기 관련

ADOBE/ ActionScript

by AlrepondTech 2020. 9. 22. 01:47

본문

반응형

 

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

출처: http://help.adobe.com/ko_KR/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e07.html

ApplicationDomain 클래스 사용

ApplicationDomain 클래스의 목적은 ActionScript 3.0 정의 표를 저장하는 것입니다. SWF 파일의 모든 코드는 응용 프로그램 도메인에 존재하도록 정의됩니다. 응용 프로그램 도메인을 사용하여 같은 보안 도메인에 있는 여러 클래스를 구분합니다. 그러면 같은 클래스에 대해 여러 가지 정의가 존재할 수 있으며 자식이 부모의 정의를 다시 사용할 수 있습니다.

Loader 클래스 API를 사용하여 ActionScript 3.0에서 작성한 외부 SWF 파일을 로드하는 경우 응용 프로그램 도메인을 사용할 수 있습니다. ActionScript 1.0 또는 ActionScript 2.0에서 작성한 이미지나 SWF 파일을 로드할 때는 응용 프로그램 도메인을 사용할 수 없습니다. 로드된 클래스에 포함된 모든 ActionScript 3.0 정의는 응용 프로그램 도메인에 저장됩니다. SWF 파일을 로드할 때 LoaderContext 객체의 applicationDomain 매개 변수를 ApplicationDomain.currentDomain으로 설정하여 Loader 객체와 동일한 응용 프로그램 도메인에 파일이 포함되도록 지정할 수 있습니다. 로드된 SWF 파일을 동일한 응용 프로그램 도메인에 저장하면 해당 클래스에 직접 액세스할 수 있습니다. 이 방법은 다음 예제와 같이 관련된 클래스 이름을 통해 액세스가 가능한 포함된 미디어가 들어 있는 SWF 파일을 로드하려는 경우나 로드된 SWF 파일의 메서드에 액세스하려는 경우에 유용합니다.

package 
{ 
    import flash.display.Loader; 
    import flash.display.Sprite; 
    import flash.events.*; 
    import flash.net.URLRequest; 
    import flash.system.ApplicationDomain; 
    import flash.system.LoaderContext; 
 
    public class ApplicationDomainExample extends Sprite 
    { 
        private var ldr:Loader; 
        public function ApplicationDomainExample() 
        { 
            ldr = new Loader(); 
            var req:URLRequest = new URLRequest("Greeter.swf"); 
            var ldrContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain); 
            ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler); 
            ldr.load(req, ldrContext);     
        } 
        private function completeHandler(event:Event):void 
        { 
            ApplicationDomain.currentDomain.getDefinition("Greeter"); 
            var myGreeter:Greeter = Greeter(event.target.content); 
            var message:String = myGreeter.welcome("Tommy"); 
            trace(message); // Hello, Tommy 
        } 
    } 
}

응용 프로그램 도메인을 사용하는 경우 주의해야 할 또 다른 사항은 다음과 같습니다.

  • SWF 파일의 모든 코드는 응용 프로그램 도메인에 존재하도록 정의됩니다. 현재 도메인은 기본 응용 프로그램이 실행되는 위치입니다. 시스템 도메인에는 현재 도메인을 포함하여 모든 응용 프로그램이 포함되므로 모든 Flash Player 클래스가 들어 있습니다.
  • 시스템 도메인을 제외한 모든 응용 프로그램 도메인에는 연결된 부모 도메인이 있습니다. 기본 응용 프로그램 도메인의 부모 도메인은 시스템 도메인입니다. 로드된 클래스는 부모가 이러한 클래스를 아직 정의하지 않은 경우에만 정의됩니다. 로드된 클래스 정의를 새 정의로 재정의할 수는 없습니다.

다음 다이어그램은 단일 도메인인 domain1.com의 다양한 SWF 파일에서 내용을 로드하는 응용 프로그램을 보여 줍니다. 로드한 내용에 따라 서로 다른 응용 프로그램 도메인이 사용될 수 있습니다. 다음에 나오는 텍스트는 응용 프로그램의 각 SWF 파일에 적합한 응용 프로그램 도메인을 설정하는 데 사용되는 논리를 설명합니다.

전체 화면으로 그래픽 보기



A. 구문 AB. 구문 BC. 구문 C

기본 응용 프로그램 파일은 application1.swf입니다. 여기에는 다른 SWF 파일에서 내용을 로드하는 Loader 객체가 포함되어 있습니다. 이 시나리오에서 현재 도메인은 Application domain 1입니다. 구문 A, 구문 B, 구문 C는 응용 프로그램에서 각 SWF 파일에 적합한 응용 프로그램 도메인을 설정하는 여러 가지 기술을 보여 줍니다.

구문 A: 시스템 도메인의 자식을 만들어 자식 SWF 파일을 구분합니다. 다이어그램에서는 응용 프로그램 도메인 2가 시스템 도메인의 자식으로 만들어집니다. application2.swf 파일이 응용 프로그램 도메인 2에 로드되므로, 해당 클래스 정의는 application1.swf에 정의된 클래스에서 구분됩니다.

이 기술은 이전 응용 프로그램에서 같은 응용 프로그램의 새 버전을 충돌 없이 동적으로 로드하는 데 사용할 수 있습니다. 같은 클래스 이름을 사용하더라도 다른 응용 프로그램 도메인으로 구분되므로 충돌이 없습니다.

다음 코드는 시스템 도메인의 자식인 응용 프로그램 도메인을 만들고 이 응용 프로그램 도메인을 사용하여 SWF 로드를 시작합니다.

var appDomainA:ApplicationDomain = new ApplicationDomain(); 
 
var contextA:LoaderContext = new LoaderContext(false, appDomainA); 
var loaderA:Loader = new Loader(); 
loaderA.load(new URLRequest("application2.swf"), contextA);

구문 B: 현재 클래스 정의에 새 클래스 정의를 추가합니다. module1.swf의 응용 프로그램 도메인이 현재 도메인(응용 프로그램 도메인 1)으로 설정됩니다. 그러므로 새 클래스 정의를 사용하여 응용 프로그램의 현재 클래스 정의 설정에 추가할 수 있습니다. 이것은 기본 응용 프로그램의 런타임 공유 라이브러리에 사용할 수 있습니다. 로드된 SWF는 RSL(Remote Shared Library)로 처리됩니다. 응용 프로그램이 시작하기 전에 프리로더로 RSL을 로드하려면 이 기술을 사용하십시오.

다음 코드는 응용 프로그램 도메인을 현재 도메인으로 설정하여 SWF를 로드합니다.

var appDomainB:ApplicationDomain = ApplicationDomain.currentDomain; 
 
var contextB:LoaderContext = new LoaderContext(false, appDomainB); 
var loaderB:Loader = new Loader(); 
loaderB.load(new URLRequest("module1.swf"), contextB);

구문 C: 현재 도메인의 새로운 자식 도메인을 만들어 부모 클래스 정의를 사용합니다. module3.swf의 응용 프로그램 도메인은 현재 도메인의 자식이며 자식은 부모 버전의 모든 클래스를 사용합니다. 이 기술은 기본 응용 프로그램 유형을 사용하는 기본 응용 프로그램의 자식으로 로드되는 다중 화면 RIA(Rich Internet Applications)의 모듈로 사용할 수 있습니다. 모든 클래스를 항상 이전 버전과 호환되도록 업데이트하고 로드하는 응용 프로그램이 로드되는 대상보다 항상 새로운 버전인 경우 자식이 부모 버전을 사용합니다. 자식 SWF에 대한 참조를 계속 포함하지 않는 경우 새 응용 프로그램 도메인을 포함하면 가비지 컬렉션의 모든 클래스 정의를 언로드할 수도 있습니다.

이 기술을 사용하면 로드된 모듈이 로더의 단일 객체 및 정적 클래스 멤버를 공유할 수 있습니다.

다음 코드는 현재 도메인의 새 자식 도메인을 만들고 이 응용 프로그램 도메인을 사용하여 SWF 로드를 시작합니다.

var appDomainC:ApplicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); 
 
var contextC:LoaderContext = new LoaderContext(false, appDomainC); 
var loaderC:Loader = new Loader(); 
loaderC.load(new URLRequest("module3.swf"), contextC);

 

 

 

=================================

=================================

=================================

 

 

 

 

출처: http://blog.jidolstar.com/474

ActionScript 3.0의 ApplicationDomain은 로드한 SWF파일 내부에 정의된 Class를 참조하는데 유용하게 쓰인다.

ApplicationDomain은 현재 hasDefinition(name:String):Boolean 과 getDefinition(name:String):Object 등 2개의 public 메소드를 지원한다. 이 메소드를 이용하여 ApplicationDomain내 정의된 클래스 정의 유무를 알 수 있고 그에 대한 참조를 얻을 수 있다. 다음은 사용 예이다.

 

?

var myInstance:DisplayObject = new
(ApplicationDomain.currentDomain.getDefinition("com.flassari.MyClass"));

 

위 코드의 경우 현재 애플리케이션의 ApplicationDomain상에 정의된 com.flassari.MyClass 클래스의 정의를 읽어와 DisplayObject 객체를 만드는 것이다. 사용하기 매우 쉽다. 그러나 클래스의 이름을 알고 있다는 전재하에 쓰일 수 있는 방법이다. 그럼 ApplicationDomain 내에 정의된 이름을 알지 못하는 클래스들의 이름을 목록을 알고 싶을 때는 어떻게 해야할까? 불행히도 ApplicationDomain 클래스는 이것을 지원해주고 있지 않다. ApplicationDomain.getAllDefinitions():Array 와 같은 메소드가 지원된다면 좋을 텐데 말이다.

 

해결방법이 있다. 바로 여기에서 소개하는 SwfClassExplorer 클래스를 이용하면 된다. 사용방법은 매우 단순하다. 하나의 static 메소드인 getClasses(bytes:ByteArray):Array 를 이용하면 된다. 아래 코드는 간단한 사용예제이다.

?

public function init():void {
    // Load the swf
    var urlLoader:URLLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
    urlLoader.addEventListener(Event.COMPLETE, onSwfLoaded);
    urlLoader.load(new URLRequest("pathToSwf"));
}


private function onSwfLoaded(e:Event):void {
    // Get the bytes from the swf
    var bytes:ByteArray = ByteArray(URLLoader(e.currentTarget).data);
    // And feed it to the SwfClassExplorer
    var traits:Array = SwfClassExplorer.getClasses(bytes);
    for each (var trait:Traits in traits) {
        trace(trait.toString()); // The full class name
    }
}

 

이는 매우 유용함을 알 수 있다. SWF를 Loader가 아닌 URLLoader로 로드했음을 볼 수 있다. 그리고 실제 DisplayObject 객체를 생성하기 위해 다음과 같이 코딩하면 되겠다.

 

?

private var _loader:Loader;


public function init():void {
    var urlLoader:URLLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
    urlLoader.addEventListener(Event.COMPLETE, onSwfLoaded);
    urlLoader.load(new URLRequest("pathToSwf"));
}


private function onSwfLoaded(e:Event):void {
    var bytes:ByteArray = ByteArray(URLLoader(e.currentTarget).data);
    var traits:Array = SwfClassExplorer.getClasses(bytes);
    for each (var trait:Traits in traits) {
        trace(trait.toString()); // The full class name
    }


    selectedClassName = traits[0];
    _loader = new Loader();
    var loaderContext:LoaderContext = new LoaderContext();
    _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderInit);
    _loader.loadBytes( bytes, loaderContext );
}


private function onLoaderInit(event:Event){
    var obj:Object;
    try {
        obj = new (_loader.contentLoaderInfo.applicationDomain.getDefinition(selectedClassName ));
    } catch (e:Error) {
        trace( "Can't instantiate class:\n" + e.toString() );
    }
    if (obj != null && obj is DisplayObject) {
        addChild( DisplayObject(obj) );
    }
}

 

결국 Binay형태로 받아온 SWF를 Loader클래스의 loadBytes()메소드를 이용해 비동기적으로 로드처리한 뒤에 Loader.contentLoaderInfo.applicationDomain의 getDefinition() 메소드를 이용해 객체를 생성하는 방식이다.

 

아쉬운 점은 여기서 loadBytes()를 이용한 비동기적 처리가 아닌 동기적 처리를 통해 클래스 참조를 얻어낼 수 있다면 더욱 좋을 것 같다.  사실 이 부분을 찾다가 이 예제를 찾아내게 된건데 매우 유용해서 포스팅 한 것이다.

 

세부적인 예제 및 소스는 아래 출처를 참고한다.

 

출처

Swf Class Explorer for AS3

소스

위 출처에서 소스를 다운받을 수 없으면 아래 링크로 다운받는다.

as3cne.zip
0.80MB

 

 

 

=================================

=================================

=================================

 

 

 

 

춣처: http://cafe.naver.com/flashdev/15980

 

[액스3.0 자문자답] 불러온 SWF 파일의 심볼 사용법. | ◈ Flash8 오픈강좌
2006.10.22 09:17
  열심멤버  
http://cafe.naver.com/flashdev/15980 

테너스 님이 지난번에 질문했던 내용이 어거였군요...제가 질문을 잘못 이해해서

답변을 못달아 드렸네요;;;

 

이것도 좋은 방법이지만 as3.0부터는 reflection 기능이 지원됩니다.

사용방법은

 

import flash.system.ApplicationDomain;

하시고 completeHandler 에서

var skinClass:Class = loader.contentLoaderInfo.applicationDomain.getDefinition( 클래스 이름 ex) "skin" ) as Class

하신 후

 

var skinA:Object = new skinClass();

var skinB:Object = new skinClass();

 

이렇게 사용하시면 됩니다.

 

 

=================================

=================================

=================================

 

 

반응형


관련글 더보기

댓글 영역