Реализация лениво загруженных модулей в VBScript

Некоторое время назад мне было нужно решение нормально импортировать библиотеки в VBScript.

VBScript, для ссылки, не имеет никакой сборки - в возможностях импорта. Традиционный метод импорта файлов состоит в том, чтобы использовать SSI, который выводит содержание включать verbatim в 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 как объект, который при доступе загрузит StringBuilder.lib и саму замену.

К сожалению, это сделано трудным печальным отсутствием VBScripts конструкций метапрограммирования. Например, нет никакого аналога Ruby method_missing, который сделал бы реализацию тривиальной.

Моя первая мысль была для основного import функционируйте для использования executeGlobal создать глобальную функцию под названием StringBuilder, берущий аргументы, которые в свою очередь загрузили бы StringBuilder.lib и затем использовали бы executeGlobal к самой "тени" (функция) с одиночным элементом StringBuilder. Существует две проблемы с этим: во-первых, использование executeGlobal определить функцию, которая затем переопределяет себя использование executeGlobal походит на довольно поверхностную идею в целом, и во-вторых, оказывается, что в VBScript, можно только переопределить функцию с переменной, если рассматриваемая функция является встроенным. Oooookay.

Следующая мысль, которую я имел, делала то же самое, кроме вместо использования executeGlobal для замены функции переменной используйте его для замены функции другой функцией, которая просто возвратила одиночный элемент. Это потребовало бы, чтобы одиночный элемент был сохранен в отдельной глобальной переменной. Недостатки к этому подходу (кроме свойственной некошерности стратегии) - то, что доступ к одиночному элементу добавил бы вызов функции наверху и что, из-за эксцентриситетов парсинга интерпретатора, одиночный элемент больше не мог использовать свойства по умолчанию.

В целом, это - довольно липкая проблема, и нечетные причуды VBScript не имеют справки. Любые идеи или предложения приветствовались бы.

9
задан Thom Smith 16 August 2010 в 22:15
поделиться