在 VBScript 中实现延迟加载模块 [英] Implementing lazy-loaded modules in VBScript

查看:24
本文介绍了在 VBScript 中实现延迟加载模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不久前,我需要一个在 VBScript 中合理导入库的解决方案.

A while back, I needed a solution to sanely import libraries in VBScript.

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

VBScript, for reference, has no build-in import capabilities. The traditional method of importing files is to use SSI, which dumps the contents of the includee verbatim into the includer. This is less-than-optimal for a number of reasons: there is no way to avoid multiple inclusion, there's no way to specify a library directory, etc. So I wrote my own function. It's fairly simple, using executeGlobal with a dictionary to keep track of imported modules and wrapping the whole thing in an object for encapsulation:

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"

无论如何,这很好用,但如果我最终不使用该库,那就需要做很多工作了.我想让它变得懒惰,以便文件系统搜索、加载和执行仅在实际使用库时才完成.由于每个库的功能仅通过与该库同名的全局范围内的单例对象来访问,这一事实简化了这一点.例如:

Anyway, this works pretty well, but it's a lot of work if I don't end up using the library. I'd like to make it lazy, so that the filesystem search, loading, and executing are only done if and when the library is actually used. This is simplified by the fact that each library's features are accessed solely through a singleton object in global scope of the same name as the library. For example:

' 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 并替换自身.

So it seems that the obvious approach is for the lazy importer to define StringBuilder as an object that, when accessed, will load StringBuilder.lib and replace itself.

不幸的是,由于 VBScripts 缺乏元编程结构,这使得这变得困难.例如,没有类似于 Ruby 的 method_missing 的类似物,这会使实现变得微不足道.

Unfortunately, this is made difficult by VBScripts sad lack of metaprogramming constructs. For instance, there is no analogue to Ruby's method_missing, which would have made the implementation trivial.

我的第一个想法是主 import 函数使用 executeGlobal 创建一个名为 StringBuilder 的全局函数,它不带任何参数,然后加载 StringBuilder.lib 然后使用executeGlobal 使用 StringBuilder 单例隐藏"自身(函数).这样做有两个问题:首先,使用 executeGlobal 定义一个函数,然后使用 executeGlobal 覆盖自身似乎是一个相当粗略的想法,其次,事实证明在 VBScript 中,如果所讨论的函数是内置函数,则只能使用变量覆盖函数.哎呀.

My first thought was for the main import function to use executeGlobal to create a global function named StringBuilder taking no arguments which would in turn load StringBuilder.lib and then use executeGlobal to "shadow" itself (the function) with the StringBuilder singleton. There are two problems with this: first, using executeGlobal to define a function which then overrides itself using executeGlobal seems like a rather sketchy idea in general, and second, it turns out that in VBScript, you can only override a function with a variable if the function in question is a builtin. Oooookay.

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

The next thought I had was doing the same thing, except instead of using executeGlobal to replace the function with a variable, use it to replace the function with another function which simply returned the singleton. This would require that the singleton be stored in a separate global variable. The disadvantages to this approach (aside from the inherent unkosherness of the strategy) are that accessing the singleton would add function call overhead and that, due to the interpreter's parsing eccentricities, the singleton could no longer use default properties.

总的来说,这是一个相当棘手的问题,而且 VBScript 的怪癖也无济于事.欢迎任何想法或建议.

Overall, it's a rather sticky problem, and VBScript's odd quirks are of no help. Any ideas or suggestions would be welcome.

推荐答案

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

Would Windows Script Components help here? http://msdn.microsoft.com/en-us/library/07zhfkh8(VS.85).aspx

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

It's basically a way to write COM components using VBScript or JScript which you can instantiate using CreateObject

这篇关于在 VBScript 中实现延迟加载模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆