2012-02-16 2 views
11

Таким образом, учитывая, что у меня есть экземпляр этого компонента:Как определить контекст, в котором находится объект ColdFusion?

foo.cfc

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

И, этот другой компонент, fooParent.cfc:

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

Допустим, я создаю экземпляры «foo» несколько различных способов:

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

Как и ожидалось, th есть выходы:

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

То, что я хочу знать, что я могу сделать, возможно, в foo.cfc, что скажет мне что-то (что-нибудь!) о том контексте, в котором в настоящее время вызывается? Поскольку все в конечном итоге живет (по крайней мере) в какой-то области, и все области являются своего рода объектом, я говорю о том, что Мне бы очень хотелось каким-то образом определить содержащийся объект из определенного объекта-объекта. В конце концов, какой-то способ построения foo.cfc так, что нечто подобное может быть мой выход из моего образца сниппета выше:

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! 

Где каждый из этих значений может быть определена путем проверки результата от прохождения getMetaData фактический содержащий ссылка на объект.

Обновление Как было предложено Micah в комментариях, я добавил к этому тег Java, поскольку я подозреваю, что он может быть прав в том, что решение может заключаться в использовании Java для самоанализа.

Update

Вместо того, чтобы оставить это как то, что, как представляется, чисто-научной дискуссии, позвольте мне объяснить, почему мне это нужно.

Я использую CFWheels ORM с включает в себя, чтобы получить обратные ссылки на мои данные, как так:

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

Это вернет мне объект, который я могу ссылаться, как так:

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 

Теперь, в моем методе «AuthSource.authenticate», я хотел бы узнать о объекте «Пользователь», в котором я содержался. В противном случае, я в конечном итоге, для вызова функции, как это, вместо того, чтобы:

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

я должен быть в состоянии рассчитывать на то, что я звоню метод на модели через авторизацию источника объект пользователя и на самом деле читать от этого объекта изнутри этого метода.

+0

Большой вопрос. Интересно, может ли JAVA иметь какую-то интроспекцию, такую ​​как функции для определения такого рода вещей. Возможно, вы можете расширить свой вопрос, добавив тег java. – Micah

+0

Почему случайный случайный вопрос по этому вопросу? Как странно .... –

ответ

4

Его очень долгое время с тех пор, как я сделал coldfusion, так что простите мой псевдокод, но я думаю, что то, что обычно происходит в подобных случаях, заключается в том, что родитель отправляет копию своего ребенка ребенку, когда он создает экземпляр ребенка. Это используется во многих шаблонах проектирования ООП, где два объекта должны взаимодействовать друг с другом в обоих направлениях, а не только родительские методы вызова для ребенка.

так что ваш ребенок класс будет определен как что-то вроде этого:

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

, а затем, когда вы используете его ...

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

parentParam будет обязательный параметр в конструкторе называется «init», поэтому у ребенка всегда есть ссылка на родителя. Тогда все ваши методы могут использовать this.parent, чтобы делать с ним вещи. В моем примере кода я делаю # this.parent.className #, но понятия не имею, что объекты coldfusion обладают таким свойством. Вероятно, вы можете использовать какое-то отражение или мета-программирование, чтобы сделать то же самое.

Пожалуйста, обратите внимание: от того, что я собираюсь, ColdFusion не имеет поддержки для строителей встроенных, так что я показываю вам является стандартным сообществом наилучшей практики с этим сайта:

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

Я извините, вы делаете колфлюс, кстати ...;)

+0

Да, ручное отслеживание ссылки на содержащий объект было моей первой мыслью. Однако я надеялся, что может быть и другое решение, кроме этого. Я подожду немного и посмотрю, не перехватит ли кто-нибудь другой подход. Спасибо, и CF действительно не так уж и плох! –

+0

Одним из неудачных результатов этого подхода является то, что cfdumps вашего объекта становятся бесконечными циклами. :( –

+0

ah, что имеет смысл, потому что у каждого объекта есть ссылка на другую. – fregas

0

Я удалил все предыдущие, поскольку это казалось нецелесообразным. Следуя вашим последующим комментариям, следующее предложение, которое, я полагаю, может быть более похоже на то, что вы пытаетесь сделать.

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

Таким образом, не авторизация источником нужно знать о родительском объекте, но в то же время кто-то аутентификации не нужно передать в имени пользователя снова. Объект (родительский объект) имеет метод обертки для аутентификации, который добавляется в имя пользователя.

Это дополнительная помощь?

+0

Я ценю ответ, но в основном ваш ответ: «Нехорошо пытаться делать то, что вы просите». Возможно, вы правы, но на самом деле это не ответ.То же самое с тем, как я могу изменить свой реальный пример - я знаю, что могу изменить его, чтобы он работал, но на самом деле это не так. Возможно, это все-таки еще один академический вопрос. –

+0

Я вижу, как вы используете то, что вам нужно - я мог бы использовать то же самое в проекте, над которым я сейчас работаю. Способ, которым я работал, состоит в том, чтобы передать родительский объект в дочерний элемент, однако это, как упоминалось, вызывает циклические ссылки, которые являются проблематичными при сериализации и приводят к необходимости использования методов для определения и определения неопределенных ссылок на родительские объекты. Мог бы обновить приведенный выше пример, чтобы проиллюстрировать, хотя это будет очень похоже на сообщение, отправленное @fregas –

+0

. Я действительно не беспокоюсь о том, что мне нужно сделать, чтобы обойти проблему в моем последнем примере - это довольно легко. Это скорее технический вопрос о том, нужно ли мне обходить его или нет, или есть ли какие-то средства для выполнения конкретной технической работы по поиску контекста данного объекта внутри этого объекта. Вероятно, лучше всего сосредоточиться на более позднем примере и больше на первом (foo.locateMe() и т. Д.). –

0

Я знаю, что это не актуально прямо сейчас, но в следующей версии CF (Zeus) есть функция, чтобы сделать это http://blogs.adobe.com/coldfusion/2011/12/19/coldfusion-zeus-potr-callstack/.

+0

Фактически, стек вызовов отличается от того, что я прошу. В моем примере каждый из трех вызовов foo.locateMe() все происходит из одного и того же места в стеке вызовов, несмотря на то, что все они содержатся в разных объектах. Это потому, что стек вызовов относится к пути выполнения (цепочки вызовов функций), а не к организации объектов в памяти. –