Как определить контекст, в котором находится объект ColdFusion? - PullRequest
11 голосов
/ 17 февраля 2012

Итак, учитывая, что у меня есть экземпляр этого компонента:

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>

Как и ожидалось, это выводит:

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 фактической ссылки на содержащий объект.

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

Обновление

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

Я использую 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"

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

Ответы [ 3 ]

4 голосов
/ 17 февраля 2012

Прошло очень много времени с тех пор, как я сделал 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 голосов
/ 17 февраля 2012

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

0 голосов
/ 17 февраля 2012

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

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

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

Это какая-то помощь?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...