2009-02-19 11 views
13

Sto creando un'API e all'interno di ciascun metodo effettuo una chiamata a un metodo di registrazione per il controllo e la risoluzione dei problemi. Qualcosa di simile:Un metodo cfc ColdFusion può determinare il proprio nome?

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

Vorrei evitare di ripetere manualmente il nome del metodo. C'è un modo per determinarlo in modo programmatico?

Ho dato un'occhiata a GetMetaData() ma restituisce solo informazioni sul componente (inclusi tutti i metodi) ma nulla sul metodo attualmente chiamato.

risposta

1

Beh si potrebbe provare questo:

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

Ho provato varie cose, e questo non è accurato come le funzioni sembrano essere aggiunto alla gamma di funzioni in ordine alfabetico inverso. Questo sembra limitare (e non risolvere il problema). Immagino che possa essere invocato un codice java nativo, ma ho bisogno di esaminarlo.

This e This sembrano interessanti letture su funzioni interne correlate.

Re: L'altra risposta su coldspring. Ho trovato this in depth article sui metadati della funzione con coldspring.

questione connessa: How to get the name of the component that’s extending mine in ColdFusion?

11

così ora 3 modi.

Se si utilizza ColdFusion 9.0 o versione successiva, ora esiste una funzione denominata GetFunctionCalledName(). Restituirà ciò che stai cercando. http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WS7cc222be8a31a47d-6e8b7083122cebfc8f2-8000.html

O

Usa Coldspring e Aspect Oriented Programming (http://www.coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=aop) per gestire questo per voi.

O

Utilizzare un cfthrow per generare una traccia dello stack che contiene le informazioni per voi:

<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> 

mia raccomandazione sarebbe di usare getFunctionCalledName, o se non su CF 9 Coldspring, come sarà probabilmente comprarti qualche altra cosa

+0

buona chiamata sulla molla fredda, ma si potrebbe pensare che non sarebbe così complicato. – ethyreal

4

Sono d'accordo con tpryan. ColdSpring rende questo molto facile. Tuttavia, ecco un'altra alternativa. Invece di analizzare la traccia dello stack, è possibile analizzare il file CFC stesso.

<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> 

Quanto sopra è scritto per ColdFusion 8. cfloop aggiunto il supporto per un ciclo su file riga per riga (e non legge l'intero file in memoria). Ho fatto alcuni test confrontando il metodo di traccia dello stack con l'analisi dei file. Entrambi hanno funzionato egregiamente su un piccolo CFC chiamato direttamente da un singolo modello CFM. Ovviamente se hai CFC molto grandi il metodo di analisi potrebbe essere un po 'più lento. D'altra parte, se si dispone di una traccia di stack di grandi dimensioni (ad esempio se si utilizza uno dei framework più diffusi), l'analisi dei file potrebbe essere più veloce.

- = Viva ColdFusion = -

1

ho pensato a un altro modo che potrebbe funzionare.

Setup un qualcosa OnMissingMethod come questo:

<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> 

quindi denominare ciascuno dei metodi regolari con un prefisso ("Nascosto" in questo esempio), e contrassegnarli come privati. Quindi il mio primo esempio sarebbe diventato:

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

Ora tutte le chiamate saranno intercettate da onMissingMethod, che aggiungerà il nome del metodo agli argomenti che vengono passati al metodo reale.

Gli svantaggi che vedo a questo sono che l'introspezione non funziona più correttamente, e devi usare gli argomenti con nome per chiamare tutte le tue funzioni. Se non si utilizzano argomenti con nome, gli argomenti modificano casualmente l'ordine nella struttura missingMethodNameArguments.

+0

questo è creativo! non ho mai pensato a un wrapper di funzioni. – ethyreal

Problemi correlati