2013-10-01 5 views
3

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

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

В идеале я хочу подражать, что я делаю в C#:

public class Foo 
{ 
    private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(typeof(Foo)); 

    public Foo() 
    { 
    } 

    public FooMethod() 
    { 
     try { 
      logger.Logger.Log(this.GetType(), log4net.Core.Level.Trace, "Entering" + MethodBase.GetCurrentMethod().Name, null); 
      // code 
     } 
     catch (e) { 
      logger.Logger.Log(this.GetType(), log4net.Core.Level.Debug, ex.Message, null); 
     } 
     finally { 
      logger.Logger.Log(this.GetType(), log4net.Core.Level.Trace, "Exiting" + MethodBase.GetCurrentMethod().Name, null); 
     } 
    } 
} 

Как я могу это сделать в Typescript? Все, что я могу сделать, это получить имя класса.

class Foo { 
    private static logger: log4javascript.Logger = log4javascript.getLogger(getName(Foo)); 

    constructor() { 
    } 

    FooFunction() { 
     try { 
      SymDataSource.logger.trace("Entering: " + getName(Foo.prototype.FooFunction)); 
      // code 
     } catch (e) { 
      SymDataSource.logger.debug("Exception: " + getName(Foo.prototype.FooFunction), e); 
     } finally { 
      SymDataSource.logger.trace("Exiting: " + getName(Foo.prototype.FooFunction)); 
     } 
    } 
} 

function getName(obj: any): string { 
    if (obj.name) { 
     return obj.name; 
    } 
    var funcNameRegex = /function (.{1,})\(/; 
    var results = (funcNameRegex).exec((<any> obj).constructor.toString()); 
    return (results && results.length > 1) ? results[1] : ""; 
} 

Имя класса возвращается правильно, но функции возвращаются как «Функция».

+0

возможно дубликат [Как получить имя типа объекта в JavaScript?] (Http://stackoverflow.com/questions/332422/how-do-i-get-the-name-of -an-objects-type-in-javascript) или [Получить объекты Имя класса во время выполнения в TypeScript] (http://stackoverflow.com/questions/13613524/get-an-objects-class-name-at-runtime- in-typescript) – Fenton

+0

Определены ли определенные типы для log4javascript ?? Я ждал их! –

+0

Я написал их сам. Загрузите в репозиторий, но не успели написать необходимые тестовые классы. – Tim

ответ

4

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

Foo.prototype.FooFunction = function() { 
    return getName(this.FooFunction); 
}; 

Здесь toString даст вам:

function() { 
    return getName(this.FooFunction); 
}; 

И вы можете увидеть, что имя функции нет между function() {.

Что вы можете сделать это создать встраиваемую функцию (с помощью удивительного жира стрелка, например, return getName(()=>this.FooFunction);) и разобрать этот местный орган функции, чтобы найти имя функции. Обратите внимание, что таким образом он по-прежнему является TypeSafe, и если вы выполняете рефакторинг переименования, нет никаких магических строк, которые выйдут из синхронизации. Таким образом, полная реализация становится:

class Foo { 
    static className = getName(Foo);  
    constructor() { 
    } 
    FooFunction() {   
      return getName(()=>this.FooFunction);    
    } 
} 

function getName(obj: any): string {  
    if (obj.name) { 
     return obj.name; 
    } 

    var funcNameRegex = /function (.{1,})\(/; 
    var results = (funcNameRegex).exec(obj.toString()); 
    var result = results && results.length > 1 && results[1]; 

    // Check to see custom implementation 
    if(!result){ 
     funcNameRegex = /return _this.(.*);/; 
     results = (funcNameRegex).exec(obj.toString()); 
     result = results && results.length > 1 && results[1]; 
    } 
    return result || ""; 
} 

console.log(Foo.className); 
var foo = new Foo(); 
console.log(foo.FooFunction()); 

который будет:

Foo 
FooFunction 
+0

Работы. Не очень волнуйся об использовании выражения, чтобы его украсть. Я пытаюсь использовать трассировку стека для получения предыдущей функции (так же, как функция GetCurrentName()), создавая ошибку и вытягивая верхнюю часть стека вызовов. http://www.codeovertones.com/2011/08/how-to-print-stack-trace-anywhere-in.html – Tim

+0

Наверное, мое решение не намного лучше, хотя и не знаю, тратит ли он ресурс. – Tim

1

Я в конечном итоге сделать две функции. 1 для текущего верхнего метода в стеке, другой для имени типа.

export function getName(): string { 
    var result: string = ""; 
    var error: any = new Error("getStack"); 
    var stack: string[] = error.stack 
     .replace(/^[^\(]+?[\n$]/gm, '') // Remove first useless line 
     .replace(/^\s+at\s+/gm, '') // Remove 'at' 
     .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') // Replace Object.<anon> with {anon} 
     .replace(/\s\(.*:[0-9]+:[0-9]+\)/gm, '') // Remove filename, col and row 
     .split('\n'); 
    return stack[1]; // Previous method 
    } 

    export function getType(obj: any): string { 
    if (obj.name) { 
     return obj.name; 
    } 
    var results = /function (.{1,})\(/.exec(obj.constructor.toString()); 
    return (results && results.length > 1) ? results[1] : ""; 
    } 
+0

примечание это ошибка.в разных браузерах разные – kofifus

Смежные вопросы