Создание собственного класса trace () в AS3 - PullRequest
4 голосов
/ 04 апреля 2009

У меня появилась идея расширить мои сообщения trace ().

Почему

trace () присутствует во всем моем коде, я хочу включить / выключить их с помощью простой команды и, возможно, добавить некоторую приоритетную функцию в trace (), т.е.

myTrace.TraceMsg("loosehere",debugme, 0);
myTrace.TraceMsg("winhere",debugme, 1);  

И когда я запускаю, отображается только тот, который имеет более высокий приоритет, в данном случае «1».

Мне бы хотелось добавить еще больше функциональных возможностей, таких как запись сообщений в файл и т. Д.

Задача

Как работает trace ()? -Можно ли как-то перегрузить trace ()? -Как я могу реализовать пользовательский метод TraceMsg (какой код здесь?)?

Возникли серьезные проблемы с поиском информации по этой теме в нашей любимой поисковой системе, поэтому любая помощь будет признательна.

Ответы [ 9 ]

5 голосов
/ 23 августа 2009

Я придумал довольно эффективный, но утомительный способ использования моей собственной функции trace () в проектах только Flash, но вызывал ее просто с помощью

trace("this", "that", "and that too");

Я в основном реализую один метод trace () в каждом классе моего проекта, который вызывает публичную функцию (чтобы я мог оттуда вызывать реальную функцию trace ().

вот что я делаю: в каждом классе я называю это

include "trace_implementation.as";

в файле .as содержится простая реализация метода (это может быть и статический метод).

public function trace(... arguments){
    for(var i in arguments){
        myTrace(arguments[i]);
    }
}

и функция myTrace определена в ее собственном файле myTrace.as

package pt.utils{
    import flash.external.ExternalInterface

    public function myTrace(_s:String):void{
        trace(_s);// this will call the original flash trace() function
        ExternalInterface.call("console.log", _s);// to get traces outside of flash IDE
            /*implement what you want here*/
    }
}

так что теперь, когда я компилирую с помощью "опустить действия трассировки", вся моя отладка игнорируется, как если бы я просто использовал trace ().

действительно хорошая сторона в том, что вы можете реализовывать пользовательские действия в зависимости от инструкций, которые вы даете в трассировке, поэтому:

trace(Debug.DEBUG_MESSAGE, "message to output in debug");
trace(Profile.START_PROFILING, this, 'name');
/*do heavy code*/
trace(Profile.STOP_PROFILING, this);

затем отправьте его из myTrace, или из класса Tracer, или из чего-либо еще:)

Надеюсь, это поможет будущим трассировщикам.

3 голосов
/ 04 апреля 2009

trace() сама по себе является функцией верхнего уровня, а не классом, поэтому, к сожалению, мы не можем ее расширить. При этом мы можем использовать его в простом классе, чтобы делать то, что он обычно делает, только в этом случае трассировка основана на условиях (т. Е. Boolean - true | false и т. Д.). Сначала мы создаем класс Trace, который мы не будем создавать, потому что мы используем шаблон проектирования Factory через класс, приведенный ниже, Tracer. Tracer построен на основе шаблона проектирования Singleton, но использует шаблон Factory для создания экземпляров Trace, когда вызывается метод trace Tracer.

//This class is handled by Tracer, which is right below it.
//You WILL NOT instantiate these, nor hold references.
package
{
    public class Trace
    {
        private function _value:*;
        private function _trace:Boolean;

        public function Trace(pValue:*, pTrace:Boolean):void
        {
          _value = pValue;
          _trace = pTrace;
        }
        public function get value():*
        {
           return _value;
        }
        public function get trace():Boolean
        {
           return _trace;
        }
    }
}
//This is the important class and the only one you will work with.
package
{
    /**
     *Utilizes Singleton and Factory design patterns.
     */
    public class Tracer
    {
        private var _traceArray:Array;
        private static var _instance:Tracer;

        public function Tracer(pvt:PrivateClass = null):void
        {
            if(pvt == null)
            {
                throw(new Error("You cannot instantiate this class directly, please use the static getInstance method."));
            }

            _init();
        }
        public static function getInstance():Tracer
        {
            if(Tracer._instance == null)
            {
                Tracer._instance = new Tracer(new PrivateClass());
            }
            return Tracer._instance;
        }
        public function trace(pValue:*, pTrace:Boolean):void
        {
           var trace:Trace = new Trace(pValue, pTrace);
           if(trace.pTrace)
           {
               trace(pValue);
           }
        }
        //Since we have the option for individual traces to be disabled
        //I provide this to get access to any and all later.
        public function traceAll():void
        {
            traceStr:String = _traceArray.toString();
        }
        public function get traceables():Array
        {
            return _traceArray;
        }
        //Here we provide a method to trace all, even if set to false in their constructor.
        private function _init():void
        {
            _traceArray = new Array();
        }
    }
}
//Here we create a class that is OUTSIDE of the package.
//It can only be accessed from within this class file.  We use this
//to make sure this class isn't instantiated directly.
class PrivateClass
{
    function PrivateClass():void
    {
        trace('can only be accessed from within this class file');
    }
}

//Now for use in doc class
package
{
    import flash.display.Sprite;
    import flash.events.Event;

    //No need to import Tracer and Trace, they are also in the
    //unnamed package.

    public class DocumentClass extends Sprite
    {
        private var _tracer:Tracer;

        public function DocumentClass():void
        {
            if(stage) _init();
            else addEventListener(Event.ADDED_TO_STAGE, _init);
        }
        private function _init(e:Event = null):void
        {
            _tracer = Tracer.getInstance();
            _tracer.trace(10*20, false);
            _tracer.trace(10*20, 0); //SAME AS ABOVE
            _tracer.trace("I love AS3", true); //traces
            _tracer.traceAll(); //Would trace: 200, 200, I love AS3
        }
    }
}

Имейте в виду, что это от бедра и вполне может иметь ошибку или два, но идея есть; То есть, это не проверено, это просто чтобы дать вам представление о том, как вы могли бы реализовать это.

Надеюсь, это поможет.

2 голосов
/ 03 ноября 2009

Вы не можете переопределить trace сам по себе, но для простоты ввода мне нравится создавать глобальную функцию с именем 'tr'. Это малоизвестный факт, что вы можете создавать глобальные функции в AS3, но это легко.

Создайте файл с именем tr.as внутри вашего основного исходного каталога (не в подкаталоге или пакете) с содержанием:

package {
  public function tr(msg:String, ...):void {
    // add custom trace logic here
    trace("tr message: "+msg);
  }
}

Если вам нужно иметь много логических или статических переменных хранения и т. Д., Может быть лучше создать отдельный статический класс и вызвать для него глобальную функцию tr, например:

package {
  import org.code.MyTracer;
  public function tr(msg:String, ...):void {
    MyTracer.tr(msg); // all the tracing logic is inside the MyTracer class
  }
}
2 голосов
/ 04 апреля 2009

Посмотрите API Flex logging , в частности, раздел: Реализация пользовательского регистратора с API logging .

Посмотрите также класс TraceTarget.

1 голос
/ 11 февраля 2011

Как упомянуто ниже, нет способа переопределить трассировку (по крайней мере, если вы не хотите, чтобы ваши трассы достигли выходного потока), но на самом деле очень легко создать собственную универсальную функцию регистрации. Кроме того, вы даже можете определить универсально доступный логический тип для включения или выключения регистрации:

log.as (обратите внимание, что имя файла должно отражать название функции)

package {
    function log(... arguments):void {

        trace("Custom logging FTW!");
        if (logEnabled)
            trace(arguments);
    }
}

logEnabled.as (обратите внимание, что имя файла должно отражать имя переменной)

package {
    var logEnabled:Boolean = true;
}

Main.as

package {

    import flash.display.MovieClip;

    public class Main extends MovieClip {

        public function Main() {
            log("Testing");
            logEnabled = false;
            log("Testing2");
        }
    }
}

Ответ

Custom logging FTW!
Testing
Custom logging FTW!
1 голос
/ 15 декабря 2010

Trace - это функция верхнего уровня, поэтому вы не можете переопределить ее, и, насколько я знаю, она не генерирует никаких событий. Поскольку это функция верхнего уровня (не содержится ни в одном из именованных пакетов), вы можете использовать ее без операторов импорта.

Ниже приведен пример класса верхнего уровня "Tracer", который можно использовать вместо трассировки без операторов импорта.

Просто вызовите «Tracer.write» или «Tracer.writeError» для отслеживания объектов Error. «Tracer.write» принимает переменное количество аргументов, как и встроенная функция трассировки. «Tracer.writeError» - это вспомогательный метод, который позволяет легко отслеживать объекты ошибок.

Особенности:

  1. Вызывает встроенную трассировку.
  2. Сохраняет журнал всех ваших вызовов Tracer.write в виде массива строк.
  3. Журнал вызовов доступен в виде строки через getText, который объединяет все элементы в массиве с символом новой строки и, при необходимости, привязывает номера строк!
  4. Запускает события, когда в журнал добавляются новые строки, поэтому, если у вас есть какое-то окно отображения журнала, оно может прослушивать события Tracer, чтобы обновлять отображение журнала в реальном времени по мере возникновения событий. Это отлично подходит для отображения событий трассировки при запуске в веб-браузере или автономном проигрывателе.

- Определение класса трейсера

package
{
    import flash.events.EventDispatcher;

    public class Tracer extends EventDispatcher
    {
        private static var traced_text:Array = new Array( "--Start of Trace Log--" );
        public static var enabled:Boolean = true;
        private static var suspended:Boolean = false;
        public static var instance:Tracer = new Tracer();
        public static const newline:String = "\n"; //workaround for TextField.appendText bug.. use "\n" instead of "\r".  See note and link to bug post in getText method

        public function Tracer()
        {
        }

        static public function write( ...args ):void
        {
            if (enabled && !suspended)
            {
                trace.apply( null, args );
                var text:String = args.join( newline );
                var next_index:int = traced_text.length;
                traced_text.push( text );
                suspended = true; //prevent recursive calls from TracerEvent handler
                instance.dispatchEvent( new TracerEvent( text, next_index ) );
                suspended = false;
            }
        }

        static public function writeError( e:Error ):void
        {
            write( "errorID: " + e.errorID, "errorName: " + e.name, "errorMessage: " + e.message, "stackTrace: " + e.getStackTrace() );
        }

        static public function getText( include_line_numbers:Boolean ):String
        {
            var line_count:int = traced_text.length;
            var lines:Array = traced_text; //store pointer to traced_text; pointer may be changed to reference an altered array that includes line numbers
            if (include_line_numbers) //create temporary trace log copy with altered lines; allows quick call to join at end
            {
                var new_lines:Array = new Array();
                for (var i:int = 0; i < line_count; i++)
                    new_lines.push( i.toString() + ": " + lines[i] );
                lines = new_lines;
            }
            return lines.join( newline ); //do not include last newline character (workaround for bug in appendText method (https://bugs.adobe.com/jira/browse/FP-1982); I have to call appendText with newline character first, otherwise it has issues like not acknoledging the newline thats already there at the end).
        }

        static public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void 
        {
             instance.addEventListener(type, listener, useCapture, priority, useWeakReference);
        }

        static public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void 
        {
            instance.removeEventListener(type, listener, useCapture);
        }

        static public function willTrigger(type:String):Boolean 
        {
            return instance.willTrigger(type);
        }

        static public function hasEventListener(type:String):Boolean 
        {
            return instance.hasEventListener(type);
        }
    }
}

-определение класса TracerEvent

package
{
    import flash.events.Event;

    public class TracerEvent extends Event
    {
        public static const WRITE:String = "te_write";

        public var text:String;
        public var index:int; //index of newly traced text in the traced_text array (trace log)

        public function TracerEvent( text:String, index:int ) 
        {
            super( WRITE, false, false );
            this.text = text;
            this.index = index;
        }

        override public function clone():Event 
        {
            return new TracerEvent( text, index );
        }
    }
}
1 голос
/ 23 августа 2009

В AS2 можно было переопределить функцию глобальной трассировки, выполнив что-то вроде этого (взятое из памяти, может быть немного неправильно, но суть в этом есть):

public static var realTrace:Function = _global["trace"];

// This is put in some init code somewhere
_global["trace"] = myTrace;

public static function myTrace(... args):void
{
    // Do whatever you want with args here, build a nice formatted string or whatever
    // before passing to realTrace. Using with MTASC one could add line numbers, class
    // names and all sorts of nice meta data. Or just return should you want to turn
    // tracing off.
    realTrace.apply(args);
}

К сожалению, я не нашел способа сделать то же самое в AS3. Тем не менее.

1 голос
/ 18 июля 2009

Вот супер простая пользовательская функция трассировки, которую я использую. Для debugFlag можно установить значение true / false в другом месте в пакете.

публичная статическая функция myTrace (... vars): void {

if (debugFlag) {
    var output:Array = new Array;
    for each (var arg in vars) {
             output.push(arg);
     }
    trace(output);
} 

}

0 голосов
/ 03 февраля 2011

вам не нужно переопределять ее, просто создайте функцию в своем проекте и вызовите ее trace, тогда любой вызов трассировки будет указывать на this.trace;)

function trace(... arguments){  
    yourfunction(arguments);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...