2017-04-10 3 views
0

현재 코드가 정의 된 조상 클래스를 프로그래밍 방식으로 어떻게 알 수 있습니까? 다음 에이전트 코드와 현재 코드가 정의 된 조상 클래스를 프로그래밍 방식으로 어떻게 알 수 있습니까?

...

Option Public 
Option Declare 
%Include "lsprcval.lss" 'defines constants used by GetThreadInfo 

Dim gNotesLog As NotesLog 

Class MyClass 
    Sub New 
     On Error GoTo ErrorSub 

     gNotesLog.LogAction "Starting " + TypeName(Me) + "." & GetThreadInfo(LSI_THREAD_PROC) 
     Error 1, "Forced error" 
     Exit Sub 
ErrorSub: 
     gNotesLog.LogError Err, TypeName(Me) + "." & GetThreadInfo(LSI_THREAD_PROC) & ":" & Erl & " " + Error$ 
     Error Err, Error$ 'throw error 
    End Sub 
End Class 

Class MyChildClass As MyClass 
    Sub New 
     On Error GoTo ErrorSub 

     gNotesLog.LogAction "Starting " + TypeName(Me) + "." & GetThreadInfo(LSI_THREAD_PROC) 
     gNotesLog.LogAction "childish code goes here" 
     Exit Sub 
ErrorSub: 
     gNotesLog.LogError Err, TypeName(Me) + "." & GetThreadInfo(LSI_THREAD_PROC) & ":" & Erl & " " + Error$ 
     Error Err, Error$ 'throw error 
    End Sub 
End Class 

Sub Initialize 
    Set gNotesLog = New NotesLog("ExampleAgent") 
    gNotesLog.OpenAgentLog 

    On Error Resume Next 
    MakeClass 
    MakeChildClass 
    gNotesLog.LogAction "Agent Complete" 
End Sub 

Sub MakeClass 
    On Error GoTo ErrorSub 
    Dim oMyClass As New MyClass 
    Exit Sub 
ErrorSub: 
    gNotesLog.LogError Err, GetThreadInfo(LSI_THREAD_PROC) & ":" & Erl & " " + Error$ 
    Error Err, Error$ 'throw error 
End Sub 

Sub MakeChildClass 
    On Error GoTo ErrorSub 
    Dim oMyChildClass As New MyChildClass 
    Exit Sub 
ErrorSub: 
    gNotesLog.LogError Err, GetThreadInfo(LSI_THREAD_PROC) & ":" & Erl & " " + Error$ 
    Error Err, Error$ 'throw error 
End Sub 

로그 출력은 다음과 같습니다 2017년 4월 10일에

시작 실행 에이전트 'StackOverflow의'오후 2시 38분 24초
04/10/2017 02:38:24 PM : 시작 MYCLASS.NEW
04/10/2017 02:38:24 PM : 오류 (1) : MYCLASS.NEW:8 강제 오류
04/10/2017 02:38:24 PM : 오류 (1) : MAKECLASS : 3 강제 오류
04/10/2017 02:38:24 PM : 시작 MYCHILDCLASS.NEW
04/10/2017 02:38:24 PM : 오류 (1) : MYCHILDCLASS.NEW:8 강제 오류
04/10/2017 02:38:24 PM : 오류 (1) : MAKECHILDCLASS : 3 강제 오류
2017년 4월 10일 오후 2시 38분 24초 : 에이전트
전체가 2017년 4월 10일에 LotusScript와 코드
완료 실행 에이전트 '에 StackOverflow를'란 오후 2시 38분 24초 :
것은 내가 좋아하지 않는다 오해의 소지가 있기 때문입니다. "MYCHILDCLASS.NEW 시작"및 다음 오류가 MyClass.New 코드 내에서 기록됩니다. MyClass.New가 해당 오류를 throw하므로 MyChildClass.New가 시작되지 않습니다.

I 거라고 차라리 참조 :

시작 실행 에이전트 '에 StackOverflow'을 2017년 4월 10일 오후 2시 38분 24초
2017년 4월 10일 오후 2시 38분 24초에 : MYCLASS.NEW
시작 04/10/2017 02:38:24 PM : 오류 (1) : MYCLASS.NEW:8 강제 오류
04/10/2017 02:38:24 PM : 오류 (1) : MAKECLASS : 3 강제 오류
2017년 4월 10일 오후 2시 38분 24초 : MyClass의 시작 (MYCHILDCLASS) .new를
2017년 4월 10일 오후 2시 38분 24초 : 오류 (1) : MyClass에 (MYCHILDCLASS) .new를 : 8 강제 오류,627,552,314,960,453,210 2017년 4월 10일 2시 38분 24초 PM : 오류 (1) : MAKECHILDCLASS : 3 강제 오류 오후
2017년 4월 10일 2시 38분 24초 : 에이전트
전체가 LotusScript와 코드
를 실행 완료를 실행 에이전트 'StackOverflow'on 04/10/2017 02:38:24 PM :
왜냐하면이 두 클래스가 모두 오류를 포함하고 있고 객체가 자손 클래스 자체에서 정의되어 있기 때문입니다.

내가 가장 간단한 솔루션에 MyClass의를 변경하는 것입니다 알고

Class MyClass 
    Sub New 
     On Error GoTo ErrorSub 
     Dim sMe As String 

     sMe = TypeName(Me) 
     If sMe <> "MYCLASS" Then 
      sMe = "MYCLASS(" + sMe + ")" 
     End If 

     gNotesLog.LogAction "Starting " + sMe + "." & GetThreadInfo(LSI_THREAD_PROC) 
     Error 1, "Forced error" 
     Exit Sub 
ErrorSub: 
     gNotesLog.LogError Err, sMe + "." & GetThreadInfo(LSI_THREAD_PROC) & ":" & Erl & " " + Error$ 
     Error Err, Error$ 'throw error 
    End Sub 
End Class 

하지만 각각의 방법에 하드 코딩 클래스 이름입니다. 클래스 이름을 문자열로 하드 코딩하거나 각 스크립트 라이브러리가 정확히 하나의 클래스로 이름이 지정되어 있다고 가정하지 않고이 작업을 수행 할 수 있습니까?

답변

0

답변이 부족하여 필자가 생각해 낸 것을 제공하기로 결정했습니다. 가능한 한 거의 예외없이, 나는 자신의 스크립트 라이브러리의 각 클래스가 있고, 모든 스크립트 라이브러리는 (다른 것들 사이) 내가 그 포함 만든 "DebuggingScripts"라이브러리 사용

  • LogErrorForObject() 기능 정보를 가져 오류 코드 &을 호출하고이를 기록합니다.나는 아래 코드를 포함하고 있지 않다. 단지 다섯 번째 인수가 객체의 이름임을 지적하고 싶다.

  • a DebuggingScriptsObjectBASE 다른 모든 클래스가 상속하는 클래스입니다. 이 클래스는 다음과 같은 방법이 있습니다

    • Public Function ToString As String은 - TypeName(Me)을 반환하지만, 오버라이드 (override) 할 수 있습니다. 예를 들어, 클래스가 대신 반환하려고 할 수 있습니다. Me.Parent.ToString() + ".Child(" & Me.MyName & ")"

    • Private Sub subRegisterModuleForToString(sClassName As String) - 지정된 클래스 이름을 호출 모듈 (스크립트 라이브러리라고도 함)과 연결합니다. 이것은 모든 클래스의 New 생성자 하위에서 호출됩니다.

    • Private Function fsToString_FromCodeClass(sCodeClass As String) As String-sCodeClass = TypeName(Me) 다음 Me.ToString()을 반환하는 경우 코드에 정의 된 어떤 클래스의 인수 감안할 때, 그렇지 않으면 반환 sCodeClass + "(" + Me.ToString() + ")" 예를 들어, "SuperClassNameWhereCodeIsDefined (클래스 이름)"

    • Private Function fsToString As String - 호출 클래스의 New 서브는 클래스 이름을 얻고 Me.fsToString_FromCodeClass에 전달하는 데 사용됩니다 캡처 호출 정보를 Me.subRegisterModuleForToString(ThisClassName$)라고합니다. 그렇지 않으면, 단지

    모든 것을 끝낼

Me.ToString()하지만 반환합니다. 이제 새로운 클래스를 만들 때마다 DebuggingScriptsObjectBASE을 확장 한 다음 New 생성자 sub에서 Me.subRegisterModuleForToString(*MyClassName*)을 호출합니다. 완료되면, 어떤 클래스의 로깅/에러 핸들링도 TypeName(Me) (예를 들어 내가 언급 한 LogErrorForObject 함수의 다섯 번째 인수)을 사용할 때마다 Me.fsToString()을 사용/통과 할 수 있습니다. 코드가 어떤 오브젝트의 수퍼 클래스 내에 정의 된 경우 로그에는 해당 수퍼 클래스의 이름과 해당 객체의 ToString() 메서드가 반환하는 값이 기록됩니다.

나는 여전히 내 클래스의 이름을 하드 코딩 할 필요가없는 솔루션을 선호하지만 각 클래스의 생성자 하위에서 Me.subRegisterModuleForToString을 한 번 호출하면 충분합니다.

%REM 
    Class DebuggingScriptsObjectBASE 
<!-- Created Jun 9, 2017 by JSmart523 --> 
<!-- If you're reading this, hover your mouse pointer over "DebuggingScriptsObjectBASE" in the Class statement after this comment. --> 
    This is intended to be the common ancestor object for all custom objects you write. The benefit is fsToString() and ToString() methods. Other classes and procedures of this script library do not require that your objects inherit from this one. 
<br> 
    The best way to use it is,<ol> 
     <li>Have all of your custom classes inherit (directly or indirectly) from this class. 
     <li>Follow the best practice of only having one class per script library, or at least create your script libraries so no classes descend from any classes within the same script library. 
     <li>In the constructor sub (New) of each class, call Me.subRegisterModuleForToString(CLASSNAME) where CLASSNAME is the name of the class. (Yes, unfortunately you have to hardcode this. No better way was found, LotusScript is not a completely reflective language and TypeName() doesn't work for parent-classes.) 
     <li>When logging errors or other debugging messages and wanting to mention the current object in your message, use Me.fsToString() to generate the name of your object. 
     <li>If <code>TypeName(Me)</code> is insufficient for the name of your object, override Me.ToString() (not Me.<em>fs</em>ToString()) to return whatever makes sense. 
    </ol> 
    If you do this then, any time your code logs something and wants to generate a string representing your object,<ul> 
     <li>if the code doing so is defined in the actual class of the object, it will still return Me.ToString(), however, 
     <li>if the code doing so is NOT defined in the actual class but in an ancestor class then, Me.fsToString() will return <span style="font-family: monospace; color: black;">sCodeClass <font style="color: blue;">+</font> "(" <font style="color: blue;">+ Me.</font>ToString<font style="color: blue;">()+</font> ")"</span>, for example "ParentClass(ChildClass)" which is much better at describing where the code in question is.</ul> 
<br> 
    If you don't follow the best practice of only havng one class per script library and instead define classes that inherit other classes within the same script lilbrary (e.g. this script library combines almost all it needs into a single script library so it is more easily packaged), but still want to inherit from this object then do not call Me.subRegisterModuleForToString nor Me.fsToString from within your class, use Me.fsToString_FromCodeClass instead and pass the name of your class as the method's argument. 
<br> 
    Also included in this class is a LogLevel integer property. You can use this in your coding to determine how verbose your logging should be, with 0 as normal. For example, if your class has a DoTheThing method you might want that method's code to be: 
<blockquote> 
<pre><div style="font-family: monospace; font-size: 9pt; color: black;"><font style="color: blue;">Class</font> YourClass <font style="color: blue;">As</font> DebuggingScriptsObjectBASE 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">Sub New()</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">If Not</font> libbDebugMode <font style="color: blue;">Then On Error GoTo</font> LogAndThrowError 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">Me.</font>subRegisterModuleForToString<font style="color: blue;">(</font><font style="color: black;">"YourClass"</font><font style="color: blue;">)</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">Exit Sub</font> 
LogAndThrowError<font style="color: blue;">:</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogErrorForObject <font style="color: blue;">Err, Erl, Error$, Me.</font>fsToString<font style="color: blue;">(),</font> <font style="color: black;">""</font><font style="color: blue;">,</font> <font style="color: black;">""</font><font style="color: blue;">,</font> <font style="color: black;">""</font><font style="color: blue;">,</font> <font style="color: purple;">True</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">End Sub</font> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">Sub</font> DoTheThing<font style="color: blue;">(</font>db <font style="color: blue;">As</font> <font style="color: black;">NotesDatabase</font><font style="color: blue;">,</font> doc <font style="color: blue;">As</font> <font style="color: black;">NotesDocument</font><font style="color: blue;">,</font> vArg3 <font style="color: blue;">As Variant)</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">If Not</font> libbDebugMode <font style="color: blue;">Then On Error GoTo</font> LogAndThrowError 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">If Me.</font>LogLevel <font style="color: blue;">&#62;</font> 0 <font style="color: blue;">Then</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">Dim</font> oIndent <font style="color: blue;">As New</font> MortalIndent<font style="color: blue;">(</font><font style="color: black;">""</font><font style="color: blue;">,</font> <font style="color: black;">"Starting "</font> <font style="color: blue;">+ Me.</font>fsToString<font style="color: blue;">() +</font> <font style="color: black;">".DoTheThing"</font><font style="color: blue;">,</font> <font style="color: black;">"Exiting "</font> <font style="color: blue;">+ Me.</font>fsToString<font style="color: blue;">() +</font> <font style="color: black;">".DoTheThing"</font><font style="color: blue;">)</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">If Me.</font>LogLevel <font style="color: blue;">&#62;</font> 1 <font style="color: blue;">Then</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogAction <font style="color: black;">"db = "</font> <font style="color: blue;">+</font> fsStringifyForDebugging<font style="color: blue;">(</font>db<font style="color: blue;">,</font> <font style="color: purple;">True</font><font style="color: blue;">)</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogAction <font style="color: black;">"doc = "</font> <font style="color: blue;">+</font> fsStringifyForDebugging<font style="color: blue;">(</font>doc<font style="color: blue;">,</font> <font style="color: purple;">True</font><font style="color: blue;">)</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogAction <font style="color: black;">"vArg3 = "</font> <font style="color: blue;">+</font> fsStringifyForDebugging<font style="color: blue;">(</font>vArg3<font style="color: blue;">,</font> <font style="color: purple;">True</font><font style="color: blue;">)</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">End If</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">End If</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: green;">'MAIN CODE WOULD GO HERE</font> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">Exit Sub</font> 
LogAndThrowError<font style="color: blue;">:</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogErrorForObject <font style="color: blue;">Err, Erl, Error$, Me.</font>fsToString<font style="color: blue;">(),</font> <font style="color: black;">""</font><font style="color: blue;">,</font> ToArray3<font style="color: blue;">(</font>db<font style="color: blue;">,</font> doc<font style="color: blue;">,</font> vArg3<font style="color: blue;">),</font> <font style="color: black;">""</font><font style="color: blue;">,</font> <font style="color: purple;">True</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">End Sub</font> 
<font style="color: blue;">End Class</font></div></pre> 
<!-- Huge thanks to Julian Robichaux's LS2HTML script at http://www.nsftools.com/tips/ls2html.lss --> 
</blockquote> 
    so that, if an object of that class has a LogLevel property value greater than zero then this script library will log when the method starts, and stops, and indent all of the log entries in the middle, and if the LogLevel value is greater than 1 then it also logs the arguments. 
    Also, if another class extends YourClass then the log messages will explain that the code is contained within YourClass, not the descendant class. 
%END REM 
Public Class DebuggingScriptsObjectBASE 

    'Private list of classes, indexed by the module (i.e. script library) they are contained in 
    Private plstsClassByModule List As String 


    %REM 
     Private Sub subRegisterModuleForToString(sClassName As String) 
     If you call <code>Me.subRegisterModuleForToString("MyClassName")</code> from your class's New sub, when this specific class calls Me.fsToString() the returned string will indicate that it was called by this specific class. This greatly helps avoid confusion when trying to figure out which class contains the code that logged the error. 
     Stores <code>sClassName</code> into a list of class names, indexed by the module (aka script library) that defines them. 
<br> 
     Unfortunately there's no way for a method to be able to tell which ancestor class or descendant class (if any) called it, but we CAN tell which <em>design element</em> contains the code that called the method. By calling this in each class's constructor sub, your objects build a "Design Element to CodeClass" map for themselves. Then, if Me.fsToString is called, while there isn't any native LotusScript to determine which class defines the code that called it, it can derrive the ClassCode via <code>Me.plstsClassByModule(GetThreadInfo(LSI_THREAD_CALLMODULE))</code> 
    <br> 
     <b>Arguments</b> 
     <blockquote><dl><dt>sClassName As String</dt><dd>Name of the class that is calling this method.</dd></dl></blockquote> 
    %END REM 
    Private Sub subRegisterModuleForToString(sClassName As String) 
     If Not libbDebugMode Then On Error GoTo LogAndThrowError 

     Dim sCallModule As String 
     sCallModule = GetThreadInfo(LSI_THREAD_CALLMODULE) 

     If Len(sClassName) = 0 Then 
      Error 13, Me.ToString() + ".subRegisterModuleForToString's argument cannot be blank." 
     ElseIf Not IsElement(Me.plstsClassByModule(sCallModule)) Then 
      'remember that script library sCallModule defines sClassName 
      Me.plstsClassByModule(sCallModule) = sClassName 
'   Me.subAddToClassNames sClassName 
     ElseIf Me.plstsClassByModule(sCallModule) <> sClassName Then 
      Error DebuggingScripts_ERROR_CodeClassConflict, {If both "} + sClassName + {" and "} + Me.plstsClassByModule(sCallModule) + {" are defined within module "} + sCallModule + {", neither should call subRegisterModuleForToString. Please either move one of the classes to its own script libraray or change that class so that all calls to Me.fsToString() instead call Me.fsToString_FromCodeClass("YourClassName")} 
     'Else 
      'We don't need to do anything. Me.plstsClassByModule(sCallModule) is already sClassName! 
     End If 
     Exit Sub 
LogAndThrowError: 
     'Replace error handling with whatever you use 
     LogErrorForObject Err, Erl, Error$, "DebuggingScriptsObjectBASE", "", sClassName, sCallModule, True 
    End Sub 

    %REM 
     Public Function ToString As String 
     Unless you override this function, returns <code>TypeName(Me)</code> 
     You can override this for a class that inherits from this one. For example, if class Foo extends this one, and a Foo object was always in the "foo" property of it's parent object, you might want Foo.ToString() to override this function with the following code: 
     <pre><div style="font-family: monospace; font-size: 9pt; color: black;"><font style="color: blue;">Public</font> <font style="color: blue;">Function</font> ToString <font style="color: blue;">As</font> <font style="color: blue;">String</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">On</font> <font style="color: blue;">Error</font> <font style="color: blue;">Resume</font> <font style="color: blue;">Next</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ToString <font style="color: blue;">=</font> DebuggingScriptsObjectBASE<font style="color: blue;">.</font><font style="color: blue;">.</font>ToString<font style="color: blue;">(</font><font style="color: blue;">)</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">If</font> <font style="color: blue;">Not</font> <font style="color: blue;">Me</font><font style="color: blue;">.</font>Parent <font style="color: blue;">Is</font> <font style="color: purple;">Nothing</font> <font style="color: blue;">Then</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">If</font> <font style="color: blue;">Me</font><font style="color: blue;">.</font>Parent<font style="color: blue;">.</font>foo <font style="color: blue;">Is</font> <font style="color: blue;">Me</font> <font style="color: blue;">Then</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ToString <font style="color: blue;">=</font> Parent<font style="color: blue;">.</font>ToString<font style="color: blue;">(</font><font style="color: blue;">)</font> <font style="color: blue;">+</font> <font style="color: black;">".foo"</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">End</font> <font style="color: blue;">If</font> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="color: blue;">End</font> <font style="color: blue;">If</font> 
<font style="color: blue;">End</font> <font style="color: blue;">Function</font></div></pre> 
<!-- Huge thanks to Julian Robichaux's LS2HTML script at http://www.nsftools.com/tips/ls2html.lss --> 
     If you override, <strong>be <i>sure</i> that your ToString code will not cause an infinite loop.</strong> Within your ToString code this probably means: 
     - Do not call Me.ToString() 
     - Do not call Me.fsToString() 
     - Do not send Me as an argument to fsStringifyForDebugging because it will try the ToString method. 
     - Do not send Me as an argument to any logging functions in this script library because they use fsStringifyForDebugging 
     - Do not call procedures where, if there's an error, any of the above might happen. 
    %END REM 
    Public Function ToString As String 
     On Error GoTo ErrorSub 
     ToString = TypeName(Me) 
ExitSub: 
     Exit Function 
ErrorSub: 
     ToString = "¿¿TypeName(Me) failed??" 
     Resume ExitSub 
    End Function 

    %REM 
     Private Function fsToString As String 
    <!-- Created Jun 9, 2017 by JSmart523 --> 
    Returns <code>fsToString_FromCodeClass(Me.plstsClassByModule(GetThreadInfo(LSI_THREAD_CALLMODULE)))</code> 
<br> 
    If the calling module isn't an index value in the list Me.plstsClassByModule (populated via Me.subRegisterModuleForToString), or the class is the last descendant class for Me, returns <code>Me.ToString()</code> 
    Otherwise returns a string like "CodeClass(ObjectToString)" where<ul><li>"CodeClass" is <code>Me.plstsClassByModule(GetThreadInfo(LSI_THREAD_CALLMODULE))</code>, and<li>"ObjectToString" is <code>Me.ToString()</code> (which is usually <code>TypeName(Me)</code>).</ul> 

    This function requires the following assumptions: 
     - Your class would have called Me.subRegisterModuleForToString("YourClassName") if you wanted to use this enhanced functionality. 
     - The design element that contains your class does not also contain any classes that extend or are an ancestor of this class. 
    Calls Me.fsToString_FromCodeClass, Me.ToString 
    %END REM 
    Private Function fsToString As String 
     Dim sModule As String 

     If Not libbDebugMode Then On Error GoTo TypeNameError 
     fsToString = TypeName(Me) 

     If Not libbDebugMode Then On Error GoTo LogAndExit 
     sModule = GetThreadInfo(LSI_THREAD_CALLMODULE) 
     If IsElement(Me.plstsClassByModule(sModule)) Then 
      fsToString = fsToString_FromCodeClass(Me.plstsClassByModule(sModule)) 
     Else 
      fsToString = Me.ToString() 
     End If 
ExitSub: 
     Exit Function 

TypeNameError: 
     fsToString = "{??Unknown object because fsToStringFailed??}" 
     LogErrorForObject Err, Erl, "Error attempting TypeName(Me): " + Error$, "DebuggingScriptsObjectBASE", "", "", "", False 
     Resume ExitSub 
LogAndExit: 
     fsToString = "{??Unknown object because fsToStringFailed??}" 
     LogErrorForObject Err, Erl, Error$, Me, "", "", "", False 
     Resume ExitSub 
    End Function 

    %REM 
     Private Function fsToString_FromCodeClass(sCodeClass As String) As String 
     Compares sCodeClass to TypeName(Me) and 
     &nbsp;&nbsp;- if the same, returns Me.ToString 
     &nbsp;&nbsp;- if different, returns <code>sCodeClass + "(" + Me.ToString + ")"</code> 
    <br> 
     <b>Arguments</b> 
     <blockquote><dl><dt>sCodeClass As String</dt><dd>Name of the class containing the code in question (as opposed to TypeName(Me) which is just the end class even if the code in question is defined within a class that TypeName(Me) descends from.</dd></dl></blockquote> 

     Called by Me.fsToString(), and any objects that want to use this standard of logging the code-defining class <em>and</em> <code>TypeName(Me)</code> in a common format but (due to having ancestor objects in the same script library) Me.fsToString() is not suitable. (For example, for portability, several classes are defined withn this "DebuggingScripts" script library, and all of them inherit from DebuggingScriptsObjectBASE.) 
    %END REM 
    Private Function fsToString_FromCodeClass(sCodeClass As String) As String 
     On Error Resume Next 
     fsToString_FromCodeClass = TypeName(Me) 'in case the next line fails 
     fsToString_FromCodeClass = Me.ToString() 
     If UCase(sCodeClass) <> TypeName(Me) And Len(sCodeClass) <> 0 Then 
      fsToString_FromCodeClass = sCodeClass + "(" + fsToString_FromCodeClass + ")" 
     End If 
    End Function 
End Class 
:

여기가 DebuggingScriptsObjectBASE 객체 내에서 언급 한 코드는