在VBScript中实现延迟加载的模块

时间:2010-08-16 22:15:44

标签: asp-classic vbscript import metaprogramming

前段时间,我需要一个能够在VBScript中灵活导入库的解决方案。

作为参考,VBScript没有内置导入功能。导入文件的传统方法是使用SSI,它将includee逐字的内容转储到包含器中。由于多种原因,这不是最优的:没有办法避免多次包含,没有办法指定库目录等等。所以我编写了自己的函数。这很简单,使用executeGlobal和字典来跟踪导入的模块并将整个事物包装在一个对象中进行封装:

class ImportFunction
    private libraries_

    private sub CLASS_INITIALIZE
        set libraries_ = Server.createObject("Scripting.Dictionary")
    end sub

    public default property get exec (name)
        if not libraries_.exists(name) then
            ' The following line will find the actual path of the named library '
            dim lib_path: set lib_path = Path.resource_path(name & ".lib", "libraries")

            on error resume next
            ' Filesystem is a class of mine; its operation should be fairly obvious '
            with FileSystem.open(lib_path, "")
                executeGlobal .readAll
                if Err.number <> 0 then 
                    Response.write "Error importing library "
                    Response.write lib_path & "<br>"
                    Response.write Err.source & ": " & Err.description
                end if
            end with
            on error goto 0

            libraries_.add name, null
        end if
    end property
end class
dim import: set import = new ImportFunction

' Example:
import "MyLibrary"

无论如何,这种方法效果很好,但如果我最终没有使用该库,那将是很多工作。我想让它变得懒惰,以便文件系统搜索,加载和执行仅在实际使用库时才进行。由于每个库的功能仅通过与库同名的全局范围内的单个对象访问,因此简化了这一过程。例如:

' StringBuilder.lib '

class StringBuilderClass ... end class

class StringBuilderModule
    public function [new]
        set [new] = new StringBuilderClass
    end function

    ...
end class
dim StringBuilder: set StringBuilder = new StringBuilderModule

import "StringBuilder"
dim sb: set sb = StringBuilder.new

所以似乎很明​​显的方法是让懒惰的导入器将StringBuilder定义为一个对象,当访问它时,它将加载StringBuilder.lib并替换它自己。

不幸的是,由于缺乏元编程结构,VBScripts很难做到这一点。例如,没有类似于Ruby的method_missing,这会使实现变得微不足道。

我的第一个想法是主import函数使用executeGlobal创建一个名为StringBuilder的全局函数,不带任何参数,而这些参数反过来会加载StringBuilder.lib,然后使用executeGlobal来使用StringBuilder单例的“shadow”本身(函数)。这有两个问题:首先,使用executeGlobal来定义一个函数,然后使用executeGlobal覆盖它自己似乎是一个相当粗略的想法,其次,事实证明,在VBScript中,你可以如果所讨论的函数是内置函数,则仅覆盖带变量的函数。 Oooookay。

我的下一个想法是做同样的事情,除了使用executeGlobal替换函数与变量,使用它来替换函数与另一个简单返回单例的函数。这将要求将单例存储在单独的全局变量中。这种方法的缺点(除了策略固有的不合理之外)是访问单例会增加函数调用开销,并且由于解释器解析偏心,单例不能再使用默认属性。

总的来说,这是一个相当棘手的问题,VBScript奇怪的怪癖没有任何帮助。任何想法或建议都会受到欢迎。

1 个答案:

答案 0 :(得分:2)

Windows Script Components会在这里提供帮助吗? http://msdn.microsoft.com/en-us/library/07zhfkh8(VS.85).aspx

这基本上是一种使用VBScript或JScript编写COM组件的方法,您可以使用CreateObject实例化