【发布时间】:2010-12-10 05:28:52
【问题描述】:
不久前,我需要一个在 VBScript 中合理导入库的解决方案。
作为参考,VBScript 没有内置的导入功能。导入文件的传统方法是使用 SSI,它将包含的内容逐字转储到包含器中。由于多种原因,这不是最理想的:无法避免多次包含,无法指定库目录等。所以我编写了自己的函数。这相当简单,使用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 单例。这有两个问题:首先,使用executeGlobal 定义一个函数,然后使用executeGlobal 覆盖自身似乎是一个相当粗略的想法,其次,事实证明在VBScript 中,您只能覆盖一个函数如果所讨论的函数是内置函数,则使用变量。哎呀。
我的下一个想法是做同样的事情,除了不是使用executeGlobal 将函数替换为变量,而是使用它将函数替换为另一个仅返回单例的函数。这将要求将单例存储在单独的全局变量中。这种方法的缺点(除了该策略固有的不合理性之外)是访问单例会增加函数调用开销,并且由于解释器的解析异常,单例不能再使用默认属性。
总的来说,这是一个相当棘手的问题,而且 VBScript 的怪癖也无济于事。欢迎任何想法或建议。
【问题讨论】:
-
伙计...这是使用经典 asp 的强烈意愿!
-
不是我的选择。相信我,这不是我对优雅代码的看法。
-
@Thom 我们总是有选择的余地,但我祝你好运。我现在不能(费心)停下来学习和思考这个问题。 :)
-
那么你有没有改进或解决过这个问题?我会说这样做:让系统处理加载不需要的东西的额外开销并定义它们,或者实现“try catch”样式的延迟加载......这是我看到的仅有的两个。只是好奇你是否找到了继续前进的方法,或者你是否想继续追求它。我也很好奇为什么要继续支持VBscript
-
没有进一步的进展。我认为最后一个选项是最好的:导入 Foo 定义了一个函数 Foo ,它将模块导入变量 Foo_ 并返回它。开销不是很多,但是缺少默认属性很烦人,因为我一直将它们用作构造函数。 (VBScript 不允许在真正的构造函数中使用参数。)
标签: asp-classic vbscript import metaprogramming