2009-02-19 3 views
13

Я создаю API, и в каждом методе я делаю вызов метода ведения журнала для аудита и устранения неполадок. Что-то вроде:Может ли метод ColdFusion cfc определить собственное имя?

<cffunction name="isUsernameAvailable"> 
    <cfset logAccess(request.userid,"isUsernameAvailable")> 
    ...... 
</cffunction> 

Я хотел бы избежать ручного повторения имени метода. Есть ли способ его программно определить?

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

ответ

1

Ну вы можете попробовать это:

<cffunction name="getFunctionName" returntype="any"> 
     <cfset meta =getMetaData(this)> 
     <cfreturn meta.functions[numberOfFunction].name> 
    </cffunction> 

Я пробовал разные вещи, и это не точно, как функции, как представляется, добавляется в массив функций в обратном алфавитном порядке. Это кажется ограниченным (и не решает проблему). Я бы предположил, что можно использовать какой-то собственный Java-код, но мне нужно будет изучить это.

This и This Посмотрите, как интересное чтение о связанных внутренних функциях.

Re: Другой ответ на coldspring. Я обнаружил this in depth article о метаданных функции с coldspring.

Связанные вопрос: How to get the name of the component that’s extending mine in ColdFusion?

11

Так что теперь 3 способа.

Если вы используете ColdFusion 9.0 или выше, теперь существует функция с именем GetFunctionCalledName(). Он вернет то, что вы ищете. http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WS7cc222be8a31a47d-6e8b7083122cebfc8f2-8000.html

ИЛИ

Использование Coldspring и аспектно-ориентированное программирование (http://www.coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=aop), чтобы справиться с этим для вас.

ИЛИ

Используйте cfthrow для создания трассировки стека, который имеет для вас информацию:

<cffunction name="determineFunction" output="FALSE" access="public" returntype="string" hint="" > 
<cfset var functionName ="" /> 
<cfset var i = 0 /> 
<cfset var stackTraceArray = "" /> 
<cftry> 
<cfthrow /> 
<cfcatch type="any"> 
    <cfset stacktraceArray = ListToArray(Replace(cfcatch.stacktrace, "at ", " | ", "All"), "|") /> 

    <!---Rip the right rows out of the stacktrace ---> 
    <cfloop index ="i" to="1" from="#ArrayLen(stackTraceArray)#" step="-1"> 
     <cfif not findNoCase("runFunction", stackTraceArray[i]) or FindNoCase("determineFunction", stackTraceArray[i])> 
      <cfset arrayDeleteAt(stackTraceArray, i) /> 
     </cfif> 
    </cfloop> 

    <!---Whittle down the string to the func name ---> 
    <cfset functionName =GetToken(stacktraceArray[1], 1, ".") /> 
    <cfset functionName =GetToken(functionName, 2, "$")/> 
    <cfset functionName =ReplaceNoCase(functionName, "func", "", "once")/> 

    <cfreturn functionName /> 
</cfcatch> 
</cftry></cffunction> 

Моя рекомендация будет использовать getFunctionCalledName, или если не на CF 9 Coldspring, как это будет, вероятно, купите вам еще кое-что.

+0

Хороший звонок на холодном приводе, но вы бы подумали, что это будет не так сложно. – ethyreal

4

Я согласен w/tpryan. ColdSpring делает это очень легко. Однако здесь есть еще одна альтернатива. Вместо разбора трассировки стека вы можете проанализировать сам файл CFC.

<cffunction name="foo" displayname="foo" hint="this is just a test function" access="public" returntype="string"> 
    <cfset var test = getFunctionName(getMetaData().path, getPageContext().getCurrentLineNo()) /> 
    <cfreturn test /> 
</cffunction> 

<cffunction name="getFunctionName" hint="returns the function name based on the line number" access="public" returntype="string"> 
    <cfargument name="filepath" type="string" required="true" /> 
    <cfargument name="linenum" type="any" required="true" /> 
    <cfset var line = "" /> 
    <cfset var functionName = "" /> 
    <cfset var i = 1 /> 
    <!---- loop over CFC by line ----> 
    <cfloop file="#ARGUMENTS.filepath#" index="line"> 
     <cfif findNoCase('cffunction', line, 1)> 
      <cfset functionName = line /> 
     </cfif> 
     <cfif i EQ ARGUMENTS.linenum><cfbreak /></cfif> 
     <cfset i++ /> 
    </cfloop> 
    <!---- parse function name ----> 
    <cfset functionName = REMatchNoCase("(\bname=[""|'])+[a-z]*[""|']", functionName) /> 
    <cfset functionName = REMatchNoCase("[""']+[a-z]*[""']", functionName[1]) /> 
    <cfset functionName = ReReplaceNoCase(functionName[1], "[""']", "", "all") /> 
    <!---- return success ----> 
    <cfreturn functionName /> 
</cffunction> 

выше написан для ColdFusion 8. CFLOOP добавлена ​​поддержка цикла по файлам построчно (и не читает весь файл в память). Я провел несколько тестов, сравнивающих метод трассировки стека и синтаксический анализ файлов. Оба одинаково хорошо работали на небольшом CFC, который вызывается непосредственно из одного шаблона CFM. Очевидно, что если у вас очень большие CFC, метод анализа может быть немного медленнее. С другой стороны, если у вас большая трассировка стека (например, если вы используете какую-либо из популярных фреймворков), тогда синтаксический анализ файлов может быть более быстрым.

- = Viva ColdFusion = -

1

я подумал о другом способе, который мог бы работать.

Setup OnMissingMethod что-то вроде этого:

<cffunction name="onMissingMethod"> 
    <cfargument name="missingMethodName" type="string"> 
    <cfargument name="missingMethodNameArguments" type="struct"> 

    <cfset var tmpReturn = ""> 
    <cfset var functionToCallName = "Hidden" & Arguments.missingMethodName> 
    <cfset arguments.missingMethodArguments.calledMethodName = Arguments.missingMethodName> 
    <cfinvoke method="#functionToCallName#" argumentcollection="#Arguments.missingMethodArguments#" returnvariable="tmpReturn" /> 
    <cfreturn tmpReturn> 
</cffunction> 

Затем название каждого из обычных методов с префиксом («Hidden» в данном примере), и пометить их как частные. Так что мой первоначальный пример стал бы:

<cffunction name="HiddenisUsernameAvailable" access="private"> 
    <cfset logAccess(request.userid,Arguments.calledMethodName)> 
    ...... 
</cffunction> 

Теперь все звонки будут перехвачены onMissingMethod, который добавит имя метода к аргументам, которые получают передаваемые в режиме реального метода.

Недостатки, которые я вижу, это то, что интроспекция перестает работать должным образом, и вы должны использовать именованные аргументы для вызова всех ваших функций. Если вы не используете именованные аргументы, аргументы будут случайным образом изменять порядок в структуре missingMethodNameArguments.

+0

thats креатив! Я никогда не думал о функциональной оболочке. – ethyreal