2009-02-19 7 views
13

Je crée une API et, au sein de chaque méthode, je lance un appel à une méthode de journalisation pour l'audit et le dépannage. Quelque chose comme:Une méthode cfc ColdFusion peut-elle déterminer son propre nom?

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

Je voudrais éviter de répéter manuellement le nom de la méthode. Y a-t-il un moyen de le déterminer par programme?

J'ai regardé GetMetaData() mais il retourne seulement des informations sur le composant (y compris toutes les méthodes) mais rien sur la méthode qui est actuellement appelée.

Répondre

1

Eh bien, vous pouvez essayer ceci:

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

J'ai essayé différentes choses, et cela ne précise que les fonctions semblent être ajoutées au tableau de fonctions dans l'ordre alphabétique inverse. Cela semble limitant (et ne résolvant pas le problème). J'imagine que du code java natif pourrait être invoqué, mais je vais devoir examiner cela.

This et This ressemblent à une lecture intéressante sur les fonctions internes connexes.

Re: L'autre réponse sur coldspring. J'ai trouvé this in depth article sur les métadonnées de fonction avec coldspring.

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

11

Alors maintenant 3 façons.

Si vous utilisez ColdFusion 9.0 ou supérieur, il existe maintenant une fonction nommée GetFunctionCalledName(). Il retournera ce que vous cherchez. http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WS7cc222be8a31a47d-6e8b7083122cebfc8f2-8000.html

OU

utilisation COLDSPRING et programmation orientée aspect (http://www.coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=aop) pour gérer cela pour vous.

OU

Utilisez un cfthrow pour générer une trace de la pile qui a l'information pour vous:

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

Ma recommandation serait utiliser getFunctionCalledName, ou sinon sur CF 9 COLDSPRING, car il sera probablement vous acheter d'autres choses.

+0

bon appel sur le coldspring, mais on pourrait penser que ce ne serait pas si compliqué. – ethyreal

4

Je suis d'accord w/tpryan. ColdSpring rend cela très facile. Cependant, voici une autre alternative. Au lieu d'analyser la trace de la pile, vous pouvez analyser le fichier CFC lui-même.

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

Ce qui précède est écrit pour ColdFusion 8. CFLOOP a ajouté le support pour le bouclage sur la ligne de fichiers par ligne (et ne lit pas le fichier en mémoire). J'ai fait quelques tests comparant la méthode de trace de pile et l'analyse de fichier. Les deux ont fonctionné aussi bien sur un petit CFC appelé directement à partir d'un seul modèle CFM. Évidemment, si vous avez de très gros CFC, la méthode d'analyse peut être un peu plus lente. D'un autre côté, si vous avez une grande trace de pile (comme si vous utilisiez l'un des cadres populaires), l'analyse de fichiers pourrait être plus rapide.

- = Viva ColdFusion = -

1

Je pensais que d'une autre manière qui pourrait fonctionner.

Configuration d'un quelque chose OnMissingMethod comme ceci:

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

nom, puis chacune des méthodes régulières avec un préfixe (dans cet exemple « Caché ») et les marquer comme privée. Donc, mon premier exemple deviendrait:

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

Maintenant, tous les appels seront interceptés par onMissingMethod, qui ajoutera le nom de la méthode aux arguments qui sont transmis à la méthode réelle. Les inconvénients que je vois à ceci sont que l'introspection ne fonctionne plus correctement, et vous devez utiliser des arguments nommés pour appeler toutes vos fonctions. Si vous n'utilisez pas d'arguments nommés, les arguments changeront aléatoirement l'ordre dans la structure missingMethodNameArguments.

+0

c'est créatif! Je n'ai jamais pensé à un wrapper de fonction. – ethyreal

Questions connexes