2009-02-19 11 views
13

Ich erstelle eine API, und innerhalb jeder Methode rufe ich eine Protokollierungsmethode für Auditing und Fehlerbehebung auf. Etwas wie:Kann eine ColdFusion-cfc-Methode ihren eigenen Namen ermitteln?

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

Ich möchte vermeiden, den Methodennamen manuell zu wiederholen. Gibt es eine Möglichkeit, es programmatisch zu bestimmen?

Ich habe GetMetaData() betrachtet, aber es gibt nur Informationen über die Komponente (einschließlich aller Methoden), aber nichts darüber, welche Methode gerade aufgerufen wird.

Antwort

1

Nun, Sie könnten versuchen, diese:

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

Ich habe verschiedene Dinge ausprobiert, und dies ist nicht genau wie die Funktionen der Anordnung von Funktionen in umgekehrter alphabetischer Reihenfolge hinzugefügt zu werden scheinen. Dies scheint einschränkend zu sein (und das Problem nicht zu lösen). Ich könnte mir vorstellen, dass ein nativer Java-Code aufgerufen werden könnte, aber ich werde mich darum kümmern müssen.

This und This aussehen wie interessante Lesung auf verwandte interne Funktionen.

Re: Die andere Antwort auf Coldspring. Ich habe this in depth article auf Funktionsmetadaten mit Coldspring gefunden.

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

11

So nun 3 Möglichkeiten.

Wenn Sie ColdFusion 9.0 oder höher verwenden, gibt es jetzt eine Funktion namens GetFunctionCalledName(). Es wird zurückgeben, wonach Sie suchen. http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WS7cc222be8a31a47d-6e8b7083122cebfc8f2-8000.html

ODER

Verwenden Coldspring und Aspect Oriented Programming (http://www.coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=aop) dies für Sie zu behandeln.

OR

ein cfthrow Verwenden Sie einen Stack-Trace zu erzeugen, die die Informationen für Sie hat:

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

Meine Empfehlung getFunctionCalledName verwenden würde, oder wenn nicht auf CF 9 Coldspring, wie es wird wahrscheinlich kauf dir ein paar andere Sachen.

+0

guten Ruf auf die Coldspring, aber Sie würden denken, es wäre nicht so kompliziert. – ethyreal

4

Ich stimme w/tpryan. ColdSpring macht dies sehr einfach. Hier ist jedoch eine andere Alternative. Anstatt den Stack-Trace zu analysieren, können Sie die CFC-Datei selbst analysieren.

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

oben Das ist für Coldfusion geschrieben 8. CFLOOP Unterstützung für Dateien Linie Looping über Zeile (und liest nicht die gesamte Datei in den Speicher). Ich habe ein paar Tests durchgeführt, bei denen die Stack-Trace-Methode mit der Dateianalyse verglichen wurde. Beide funktionierten gleich gut auf einem kleinen CFC, der direkt von einer einzelnen CFM-Vorlage aufgerufen wurde. Offensichtlich, wenn Sie sehr große CFCs haben, könnte die Parsing-Methode etwas langsamer sein. Auf der anderen Seite, wenn Sie einen großen Stack-Trace haben (wie wenn Sie eines der gängigen Frameworks verwenden), dann kann Dateianalyse schneller sein.

- = Viva Coldfusion = -

1

ich einer anderen Art und Weise gedacht, die funktionieren könnte.

-Setup ein OnMissingMethod etwas wie folgt aus:

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

Dann mit einem Präfix jeder der regulären Methoden nennen („Hidden“ in diesem Beispiel), und sie als privat kennzeichnen. So würde mein erstes Beispiel werden:

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

nun alle Anrufe von onMissingMethod abgefangen werden, die den Namen der Methode auf die Argumente werden hinzufügen, die auf die reale Methode übergeben bekommen.

Die Nachteile, die ich sehe, sind, dass Introspektion nicht mehr richtig funktioniert, und Sie müssen benannte Argumente verwenden, um alle Ihre Funktionen aufzurufen. Wenn Sie keine benannten Argumente verwenden, ändern die Argumente die Reihenfolge in der missingMethodNameArguments-Struktur nach dem Zufallsprinzip.

+0

das ist kreativ! Ich habe nie über einen Funktionswrapper nachgedacht. – ethyreal

Verwandte Themen