2010-08-16 7 views
9

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.

+6

uomo ... E' una forte volontà di utilizzare ASP classico proprio lì! – cregox

+0

Non è la mia scelta. Credimi, questa non è la mia idea di codice elegante. –

+0

@Thom abbiamo sempre una scelta, ma ti auguro buona fortuna.Non posso (disturbare) smettere di imparare e pensare a questo adesso. :) – cregox

risposta