Un po 'di tempo fa, avevo bisogno di una soluzione per importare le librerie in VBScript.Implementazione di moduli lazy-loaded in VBScript
VBScript, per riferimento, non ha capacità di importazione incorporate. Il metodo tradizionale di importazione dei file consiste nell'utilizzare SSI, che esegue il dump del contenuto del includee letteralmente nel comprender. Questo è meno che ottimale per una serie di motivi: non c'è modo di evitare l'inclusione multipla, non c'è modo di specificare una directory di libreria, ecc. Così ho scritto la mia funzione. E 'abbastanza semplice, utilizzando executeGlobal
con un dizionario per tenere traccia dei moduli importati e avvolgendo il tutto in un oggetto per l'incapsulamento:
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"
In ogni caso, questo funziona abbastanza bene, ma è un sacco di lavoro se I don' t finire usando la libreria. Mi piacerebbe renderlo pigro, in modo che la ricerca, il caricamento e l'esecuzione del filesystem vengano eseguiti solo se e quando la libreria viene effettivamente utilizzata. Ciò è semplificato dal fatto che le funzionalità di ciascuna libreria sono accessibili esclusivamente attraverso un oggetto singleton con scope globale con lo stesso nome della libreria. Ad esempio:
' 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
Così sembra che l'approccio ovvio all'importatore pigro per definire StringBuilder come un oggetto che, quando accede, caricherà StringBuilder.lib e sostituire stessa.
Sfortunatamente, ciò è reso difficile da VBScript per la mancanza di metaprogrammazione dei costrutti. Ad esempio, non esiste un analogo a Ruben method_missing
, che avrebbe reso l'implementazione banale.
Il mio primo pensiero è stato per la funzione principale import
utilizzare executeGlobal
per creare una funzione globale chiamato StringBuilder prendere alcun argomento che a sua volta carico StringBuilder.lib e quindi utilizzare executeGlobal
di "ombra" in sé (la funzione) con la StringBuilder singleton. Ci sono due problemi con questo: in primo luogo, usando executeGlobal
per definire una funzione che poi si sovrascrive usando executeGlobal
sembra un'idea piuttosto schematica in generale, e in secondo luogo, si scopre che in VBScript, si può solo sovrascrivere una funzione con una variabile se la funzione in questione è integrata. Oooookay.
Il prossimo pensiero che stavo facendo era la stessa cosa, tranne invece di usare executeGlobal
per sostituire la funzione con una variabile, usarla per sostituire la funzione con un'altra funzione che restituiva semplicemente il singleton. Ciò richiederebbe che il singleton sia memorizzato in una variabile globale separata. Gli svantaggi di questo approccio (a parte l'insanabile inerzia della strategia) sono che l'accesso al singleton aggiungerebbe una funzione overhead e che, a causa delle eccentricità di parsing dell'interprete, il singleton non poteva più usare le proprietà di default.
Nel complesso, si tratta di un problema piuttosto appiccicoso e le stranezze di VBScript non sono di alcun aiuto. Qualsiasi idea o suggerimento sarebbe gradita.
uomo ... E' una forte volontà di utilizzare ASP classico proprio lì! – cregox
Non è la mia scelta. Credimi, questa non è la mia idea di codice elegante. –
@Thom abbiamo sempre una scelta, ma ti auguro buona fortuna.Non posso (disturbare) smettere di imparare e pensare a questo adesso. :) – cregox