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

Tho*_*ith 9 import vbscript metaprogramming asp-classic

前段时间,我需要一个解决方案来在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"
Run Code Online (Sandbox Code Playgroud)

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

' 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
Run Code Online (Sandbox Code Playgroud)

 

import "StringBuilder"
dim sb: set sb = StringBuilder.new
Run Code Online (Sandbox Code Playgroud)

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

不幸的是,VBScripts令人遗憾的是缺乏元编程结构.例如,Ruby没有类似的东西method_missing,这会使实现变得微不足道.

我的第一个想法是import使用main 函数来executeGlobal创建一个名为StringBuilder的全局函数,该函数不带任何参数,这些参数反过来会加载StringBuilder.lib,然后使用executeGlobalStringBuilder单例"阴影"本身(函数).这有两个问题:首先,使用executeGlobal定义一个函数然后覆盖它自己executeGlobal看起来像一个相当粗略的想法,其次,事实证明,在VBScript中,你只能用函数覆盖一个函数问题是内置的.Oooookay.

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

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

小智 2

Windows 脚本组件在这里有帮助吗?http://msdn.microsoft.com/en-us/library/07zhfkh8(VS.85).aspx

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