不久前,我需要一个解决方案来在VBScript中合理地导入库。
作为参考,VBScript没有内置的导入功能。导入文件的传统方法是使用SSI,它将includee的内容逐字转储到includer中。这不是最佳的,原因有很多:无法避免多次包含,无法指定库目录等,所以我编写了自己的函数。它相当简单,使用
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定义为一个对象,当被访问时,该对象将被加载字符串生成器.lib换掉它自己。
method_missing
,这将使实现变得微不足道。
我的第一个想法是主要的
import
要使用的函数
创建一个名为StringBuilder的全局函数,该函数不接受任何参数,而这些参数反过来会加载字符串生成器.lib然后使用
执行全局
使用StringBuilder单例对自身(函数)进行“阴影化”。这有两个问题:第一,使用
执行全局
定义一个函数,然后使用
执行全局
我的下一个想法是做同样的事情,除了不用
执行全局
若要用变量替换函数,请使用它将函数替换为另一个只返回单例的函数。这需要将单例存储在一个单独的全局变量中。这种方法的缺点(除了策略固有的不可知性之外)是,访问singleton会增加函数调用开销,并且由于解释器的解析异常,singleton不能再使用默认属性。