2012-02-16 5 views
11

Por lo tanto, teniendo en cuenta que tengo una instancia de este componente:¿Cómo determino el contexto en el que reside un objeto ColdFusion?

foo.cfc

<cfcomponent> 
    <cffunction name="locateMe"> 
    <cfreturn "I don't know where I live!"> 
    </cffunction> 
</cfcomponent> 

Y, este otro componente, fooParent.cfc:

<cfcomponent> 
    <cfset this.foo = createObject("component", "foo")> 
</cfcomponent> 

Digamos que crear instancias de "foo" de algunas maneras diferentes:

<cfset myStruct = {}> 
<cfset myStruct.foo = createObject("component", "foo")> 

<cfset myFoo = createObject("component", "foo")> 

<cfset myFooParent = createObject("component", "fooParent")> 

<cfoutput> 
#myStruct.foo.locateMe()#<br> 
#myFoo.locateMe()#<br> 
#myFooParent.foo.locateMe()#<br> 
</cfoutput> 

Como esperaba, th es salidas:

I don't know where I live! 
I don't know where I live! 
I don't know where I live! 

Lo que yo quiero saber es, ¿qué puedo hacer posiblemente dentro foo.cfc que me diga algo (cualquier cosa) sobre el contexto en el que se invoca? Como todo finalmente vive en (al menos) ámbito de algún tipo, y todos los ámbitos son un tipo de objeto, lo que estoy diciendo es que me gustaría de alguna manera determinar el objeto que contiene, desde dentro de un objeto instanciado dado. En última instancia, una cierta manera de construir foo.cfc para que algo como esto podría ser mi salida, desde mi fragmento de ejemplo anterior:

I live within a "class coldfusion.runtime.Struct" instance! 
I live within a "class coldfusion.runtime.VariableScope" instance! 
I live within a "component cfjunk.fooParent" instance! 

donde cada uno de esos valores se puede determinar examinando el resultado de pasar la getMetaData real que contiene referencia de objeto

Actualización Según lo sugerido por Micah en los comentarios, he agregado la etiqueta "Java" a esto, ya que sospecho que podría estar en lo cierto ya que la solución puede estar en el uso de Java para la introspección.

actualización

En lugar de dejar esto como lo que parece ser una discusión puramente académica, permítanme explicar por qué necesito esto.

estoy usando CFWheels ORM con incluye referencias a volver a mis datos, así:

var user = model("User").findOne(where="id=123", include="AuthSource", returnAs="object"); 

Se volverá a mí un objeto que pueda hacer referencia a este modo:

user.id // property of the "User" model 
user.reset() // method on the "User" model 
user.AuthSource.id // property of the "AuthSource" model 
user.AuthSource.authenticate(password) // method on the "AuthSource" model 

Ahora, dentro de mi método "AuthSource.authenticate", me gustaría saber sobre el objeto "Usuario" en el que estoy dentro. De lo contrario, el resultado final será tener que llamar a la función como ésta, en su lugar:

user.AuthSource.authenticate(user, password) // note the redundancy in the use of "user" 

yo debería ser capaz de confiar en el hecho de que estoy llamando al método en el modelo AuthSource a través del objeto de usuario y leer realmente desde ese objeto desde dentro de ese método.

+0

Una gran pregunta. Me pregunto si JAVA podría tener algunas funciones de introspección para determinar este tipo de cosas. Tal vez podría ampliar su pregunta agregando una etiqueta java. – Micah

+0

¿Por qué downvote al azar en esta pregunta? Qué extraño ... –

Respuesta

4

Ha pasado mucho tiempo desde la última vez que he hecho coldfusion, así que perdona mi pseudocódigo, pero creo que lo que uno normalmente hace en este tipo de casos, es que el padre envíe una copia de sí mismo al niño, cuando instancia al niño. Esto se usa en muchos patrones de diseño de OOP donde dos objetos necesitan comunicarse entre sí de ambas maneras, no solo los métodos de llamada de los padres en el niño.

por lo que su clase hija se definiría como algo parecido a esto:

<cfcomponent> 
    <cffunction name="init"> 
    <cfargument name="parentParam" required="yes" type="object"> 
    <cfset this.parent = parentParam > 
     <cfreturn this> 
    </cffuncton> 
    <cffunction name="locateMe"> 
    <cfreturn "I belong to #this.parent.className# !"> 
    </cffunction> 
<cffunction name="doOtherStuff"> 
    <cfreturn "I do stuff with my parent: #this.parent.className# !"> 
    </cffunction> 
</cfcomponent> 

y luego cuando lo utiliza ...

<cfset myParent.child = createObject("component", "Object").init(myParent) /> 
#myparent.locateMe()# 
#myparent.doOtherStuff()# 

parentParam sería un parámetro necesario en un método constructor llamado "init", por lo que el niño siempre tiene una referencia a su padre. Entonces todos sus métodos pueden hacer uso de este. Padre para hacer cosas con él. En mi ejemplo de código, hago # this.parent.className # pero no tengo idea de que los objetos coldfusion tengan dicha propiedad. Probablemente pueda usar la reflexión o meta-programación de algún tipo para hacer lo mismo.

Tenga en cuenta: Por lo que sé, ColdFusion no tiene soporte para los constructores incorporados, por lo que les muestro es un estándar de la comunidad las mejores prácticas de este sitio:

http://www.iknowkungfoo.com/blog/index.cfm/2007/8/22/Object-Oriented-Coldfusion--1--Intro-to-Objectcfc

estoy siento que está haciendo colfusion por cierto ...;)

+0

Sí, hacer un seguimiento manual de una referencia al objeto que contiene fue lo primero que pensé. Sin embargo, esperaba que pudiera haber una solución que no fuera eso. Esperaré un poco y veré si alguien más responde con un enfoque diferente. Gracias, ¡y CF realmente no es tan malo! –

+0

Un resultado desafortunado de este enfoque es que los cfdumps de su objeto se vuelven bucles infinitos. :( –

+0

ah, eso tiene sentido, porque cada objeto tiene una referencia de regreso al otro. – fregas

0

he quitado todos los anteriores, ya que parecía no ser útil. Después de sus comentarios posteriores, la siguiente es una sugerencia que creo que puede estar más abajo de lo que pretende hacer.

// Object 
<cfcomponent displayname="Object"> 
    <cffunction name="init"> 
     <cfargument name="username" type="string"> 
     <cfscript> 
      variables.username = arguments.username; 
      variables.authSource = CreateObject('component','AuthSource').init(); 
     </cfscript> 
     <cfreturn this> 
    </cffunction> 
    <cffunction name="authenticate"> 
     <cfargument name="password" type="string"> 
     <cfreturn variables.authSource.authenticate(variables.username,arguments.password)> 
    </cffunction> 
</cfcomponent> 

<cfcomponent displayname="AuthSource"> 
    <cffunction name="init"> 
     <cfreturn this> 
    </cffunction> 
    <cffunction name="authenticate"> 
     <cfargument name="username" type="string"> 
     <cfargument name="password" type="string"> 

      .... DO STUFF ... 

     <cfreturn ...> 
    </cffunction> 
</cfcomponent> 

<cfscript> 
    objUser = CreateObject('component','Object').init('SomeUserName'); 
    // Authenticate 
    objUser.authenticate('SomePassword'); 
</cfscript> 

De esta manera, AuthSource no necesita saber sobre el objeto padre, sin embargo, al mismo tiempo autenticación alguien no tiene que pasar el nombre de usuario nuevo. El objeto (objeto principal) tiene un método contenedor para la autenticación que agrega en el nombre de usuario.

¿Es esto de alguna otra ayuda?

+0

Agradezco la respuesta, pero básicamente tu respuesta es "No es una buena idea intentar hacer lo que me pides". Puede que tengas razón, pero esa no es realmente una respuesta a la pregunta.Lo mismo con la forma en que podría cambiar mi ejemplo real: sé que puedo cambiarlo para que funcione, pero eso no es realmente lo que está en juego. Quizás todavía es una cuestión académica después de todo. –

+0

Veo un uso para lo que buscas: podría utilizarlo en el proyecto en el que estoy trabajando actualmente. La forma en que trabajé a su alrededor es pasarle el objeto primario al niño, sin embargo, esto como se menciona produce referencias circulares que son problemáticas cuando se serializa y ha llevado a requerir métodos para seguir definiendo y redefiniendo las referencias de objetos padre. Podría actualizar el ejemplo anterior para ilustrarlo, aunque terminará siendo bastante similar al publicado por @fregas –

+0

. No estoy realmente preocupado por lo que tengo que hacer para solucionar el problema en mi último ejemplo, eso es bastante fácil. Es más una cuestión técnica sobre si debo o no tener que trabajar en ello, o si hay algún medio para hacer el trabajo técnico específico de encontrar el contexto de un objeto dado desde ese objeto. Probablemente sea mejor enfocarse menos en el ejemplo posterior y más en el primero (foo.locateMe() etc ....). –

0

sé que esto no es relevante en este momento, pero la próxima versión de CF (Zeus) tiene una función para hacer esto http://blogs.adobe.com/coldfusion/2011/12/19/coldfusion-zeus-potr-callstack/.

+0

En realidad, la pila de llamadas es diferente de lo que estoy pidiendo. En mi ejemplo, cada una de las tres llamadas a foo.locateMe() se originan todas en la misma ubicación en la pila de llamadas, a pesar de que todas están contenidas en diferentes objetos. Esto se debe a que la pila de llamadas se refiere a la ruta de ejecución (cadenas de llamadas a funciones), en lugar de la organización de los objetos en la memoria. –

Cuestiones relacionadas