如何以编程方式知道当前代码在哪个祖先类中定义?

时间:2017-04-10 20:08:29

标签: lotusscript

如何以编程方式知道当前代码在哪个祖先类中定义?

使用以下代理商代码......

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

日志输出为:

开始运行代理' StackOverflow'在04/10/2017 02:38:24 PM
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强制错误
04/10/2017 02:38:24 PM:代理商完成
Ran LotusScript代码
完成运行代理' StackOverflow'在04/10/2017 02:38:24 PM:
 我不喜欢,因为它有误导性。 "启动MYCHILDCLASS.NEW"并且MyClass.New中的代码记录了以下错误。因为MyClass.New会抛出该错误,MyChildClass.New甚至无法启动!

我更愿意看到:

开始运行代理' StackOverflow'在04/10/2017 02:38:24 PM
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:开始 MYCLASS(MYCHILDCLASS) .NEW
04/10/2017 02:38:24 PM:错误(1): MYCLASS(MYCHILDCLASS) .NEW:8强制错误
04/10/2017 02:38:24 PM:错误(1):MAKECHILDCLASS:3强制错误
04/10/2017 02:38:24 PM:代理商完成
Ran LotusScript代码
完成运行代理' StackOverflow'在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

但每个方法中都有硬编码的类名。有没有办法在没有将类名硬编码到字符串中的情况下执行此操作,也不假设每个脚本库一直以其中的一个类命名?

1 个答案:

答案 0 :(得分:0)

由于缺乏答案,我决定提供我想出的东西。除了尽可能少的例外,我将每个类都放在自己的脚本库中,并且每个脚本库都使用&#34; DebuggingScripts&#34;我创建的库包含(除其他外):

  • LogErrorForObject()函数,用于获取有关错误和信息的信息。调用代码并记录它。我不包括下面的代码,我只想指出它的第五个参数是对象的名称。

  • 我所有其他类继承的DebuggingScriptsObjectBASE类。该类有以下方法:

    • Public Function ToString As String - 返回TypeName(Me)但可以覆盖。例如,某个类可能希望返回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() + ")",例如&#34; SuperClassNameWhereCodeIsDefined(类名)&#34;

    • Private Function fsToString As String - 如果调用类的New子名为Me.subRegisterModuleForToString(ThisClassName$),则调用捕获的信息将用于获取类名并将其传递给{ {1}}。否则,只需返回Me.fsToString_FromCodeClass

尽管如此,所有这些都已经完成了。现在,每当我创建一个新类时,我都会确保它扩展Me.ToString(),然后在DebuggingScriptsObjectBASE构造函数子中调用Me.subRegisterModuleForToString(*MyClassName*)。完成后,这些类中的任何日志记录/错误处理都可以使用/传递New,否则他们会使用Me.fsToString()(例如我提到的TypeName(Me)函数的第5个参数。如果代码是在任何对象的超类中定义的,则日志会记录该超类的名称以及该对象的LogErrorForObject方法返回的任何内容。

我仍然希望找到一个解决方案,我根本不需要对我的班级名称进行硬编码,但只需在每个班级的构造函数子调用{{1足够可接受了。

这是我在DebuggingScriptsObjectBASE对象中提到的代码:

ToString()