Pregunta

¿ASP Classic tiene una función que sea equivalente a " de PHP; incluir una vez " característica?

¿Fue útil?

Solución

Sé que este es un tema antiguo, pero pensé agregar mis dos centavos en caso de que alguien esté interesado.

Escribí una función que hace exactamente lo que quieres: incluye el archivo dado exactamente uno, sin importar cuántas veces se haya llamado.

class ImportFunction
    private libraries_
    private fso_

    private sub CLASS_INITIALIZE
        set libraries_ = Server.createObject("Scripting.Dictionary")
        set fso_ = Server.createObject("Scripting.FileSystemObject")
    end sub

    public default property get func (path)
        if not libraries_.exists(path) then

            on error resume next
            with fso_.openTextFile(path)
                executeGlobal .readAll
                if Err.number <> 0 then 
                    Response.write "Error importing library "
                    Response.write path & "<br>"
                    Response.write Err.source & ": " & Err.description
                end if
            end with
            on error goto 0

            libraries_.add path, null
        end if
    end property
end class
dim import: set import = new ImportFunction

Notas:

  • Esto utiliza una función falsa simulada con una propiedad predeterminada. Si esto te molesta, se refactoriza fácilmente.
  • El diccionario debe ser persistente a través de todas las inclusiones, mientras que persistir en el fso simplemente evita reconstruirlo. Si no le gusta la idea de mantenerlos después de que se realicen las importaciones, puede modificar la clase para obtener una sintaxis como esta:

    with new Importer
        .import "foo"
        .import "bar/baz"
    end with
    

Otros consejos

No. Lo siento. Tienes que gestionar te incluye a ti mismo.

Este fue uno de los problemas que encontré por primera vez después de heredar una aplicación ASP heredada. Mi solución actualmente es incluir todos los archivos genéricos de la biblioteca en un archivo llamado 'app-init.asp'. Este archivo se incluye en todas las páginas y le brinda un único punto de entrada para conectar la funcionalidad de la aplicación y una base sobre la cual construir.

Gracias Thom Smith por su código.

Debajo de una versión basada en la suya para manejar archivos fuente UTF8 (y quién administra abrir & amp; cerrar etiquetas ASP).

Dim IncludeOnce
Class IncludeOnceClass

    Private libraries_
    Private adostream_

    Private Sub CLASS_INITIALIZE
        Set libraries_ = Server.createObject("Scripting.Dictionary")
        Set adostream_ = CreateObject("ADODB.Stream")
        adostream_.CharSet = "utf-8"
        adostream_.Open
    End Sub

    Public Default Property Get includeFile (path)
        Dim lpath : lpath=LCase(path)
        if Not libraries_.exists(lpath) then
            Dim code
            libraries_.add LCase(lpath), "stuff"
            On Error Resume Next
            adostream_.LoadFromFile(lpath)
            code = Replace(Replace(adostream_.ReadText(),"<"&"%",""),"%"&">","")
            executeGlobal code
            If Err.number <> 0 Then 
                Response.write "Error importing library "
                Response.write lpath & "<br>"
                Response.write Err.source & ": " & Err.description
                Response.write "<pre><tt>" & replace(code,"<","&lt;") & "</tt></pre>"
                Response.End
            End if
            On Error Goto 0
        End If
    End Property

End Class

Set IncludeOnce = new IncludeOnceClass

Como puede ver, no cierro la transmisión para permitir que se procesen más inclusiones.

Actualización: Dado que las rutas no distinguen entre mayúsculas y minúsculas, esta versión las convierte en minúsculas antes de agregarlas al Diccionario como claves. También se agregan antes de la evaluación del código, para evitar evaluaciones duplicadas en caso de bucle de inclusión (recursividad):

Dado A.asp y B.asp:

' A.asp
IncludeOnce Server.MapPath("/some/path/B.asp")

' B.asp
IncludeOnce Server.MapPath("/some/path/A.asp")

Dado que A aún no se evalúa en absoluto en la inclusión de código B, el segundo IncludeOnce ocurrirá una evaluación duplicada si aún no está registrado en el diccionario, lo que no queremos. Esta actualización soluciona el problema.

Lo mejor que puede hacer es usar SSI para incluir archivos:

http://en.wikipedia.org/wiki/Server_Side_Includes

Como advertencia a la Respuesta usando ExecuteGlobal; Creo que ExecuteGlobal crea inestabilidad ya que VBScript no recolecta basura ni administra bien la memoria. Puede arrojar & Quot; Fallo catastrófico & Quot; o " ASP 0240 Script Engine Exception " errores porque está redefiniendo un objeto que no se eliminó correctamente.

Entonces, para usar esto, también necesitaría hacer sus inclusiones, las clases que tienen destructores y la inclusión deberían crear una instancia de la clase, persistir el nombre del objeto en el diccionario y el destructor ImportFunction debería destruir todos los objetos en el diccionario.

Las inclusiones no deben tener como prefijo las etiquetas ASP <%% > tampoco, mientras que usando un #include, necesitarías.

También debe tener en cuenta que ExecuteGlobal considera que todas las X = Y son asignación y no comparación, por lo que:

isMatch = (X = Y) 'puede producir resultados espurios.

El ejemplo incluye: -

Class aClass

    Public Sub doSomething()
        ...
    End Sub

End Class

Dim instance
Set instance = new aClass

He creado un ejemplo similar al anterior, pero usando el segundo estilo de pasar la inclusión a una Sub o asignación de propiedad

Lo que también hace es intentar recolectar basura destruyendo todos los objetos del diccionario, en su propio destructor. También elimina las etiquetas asp de las bibliotecas que envolvió.

<% 
Class Libraries

private m_LoadedLibraries
private m_FileSystem

Private Property Get LoadedLibraries
    If Not isInstantiated( m_LoadedLibraries ) Then
        Set m_LoadedLibraries = Server.CreateObject("Scripting.Dictionary")
    End If
    Set LoadedLibraries = m_LoadedLibraries
End Property

Private Property Get FileSystem
    If Not isInstantiated( m_FileSystem ) Then
        Set m_FileSystem = Server.CreateObject("Scripting.FileSystemObject")
    End If
    Set FileSystem = m_FileSystem
End Property

Private Property Get IncludePath
    IncludePath = "c:\include\"
End Property

Private Property Get LibrarySuffix
    LibrarySuffix = ".inc.asp"
End Property

Private Sub Class_Terminate()

    destroyObjects

    Set m_LoadedLibraries   = Nothing
    Set m_FileSystem        = Nothing

End Sub

Private Sub destroyObjects()
    Dim objectName
    For Each objectName in LoadedLibraries.Items
        If Eval("IsObject(" & objectName & ")") Then
            Execute "Set " & objectName & " = Nothing"
        End If
    Next
End Sub

Public Sub Include(ByVal libraryName, ByVal objectName)

    libraryName = LCase( libraryName )
    Dim library, filePath, script

    If Not LoadedLibraries.Exists( libraryName ) Then
        filePath = IncludePath + libraryName + LibrarySuffix 
        Set library = FileSystem.OpenTextFile( filePath  )
        script = library.ReadAll
        script = stripAspTags( script )
        ExecuteGlobal script
        library.Close
        LoadedLibraries.add libraryName, objectName
    End If

End Sub

Private Function stripAspTags(ByVal script)
    Dim buffer, location, startTag, stopTag, tagLength 

    startTag    = Chr(60) + "%"
    stopTag     = "%" + Chr(62)
    script      = CStr( script )
    tagLength   = Len(startTag)
    location = InStr(1, script, startTag, 1 )

    If location > 0 Then
        buffer = cleanString( Left( script, location + tagLength - 1  ) )
         ' Only strip off if it's the first part of the script
        If Len( buffer ) = Len(startTag) Then
            script = Mid( script, location + tagLength )
        End If
    End If

    location = InStrRev(script, stopTag, -1, 1 )
    If location > 0 Then
        buffer = cleanString( Mid( script, location ) )
         ' Only strip off if it's the last part of the script
        If Len( buffer ) = Len(stopTag) Then
            script = Left( script, location - 1 )
        End If
    End If
    stripAspTags = script
End Function

Private Function cleanString(ByVal target)
    Dim objRegExp

    Set objRegExp           = New Regexp

    objRegExp.IgnoreCase    = True
    objRegExp.Global        = True
    objRegExp.Pattern       = "[\x00-\x1f]+"
    cleanString             = objRegExp.Replace( target, "")

    Set objRegExp = Nothing
End Function

Private Function isInstantiated(ByVal target)
    isInstantiated = ( IsNull( target) Or IsEmpty( target ) Or Not IsObject( target) )
End Function    


End Class

Dim RequireOnce
Set RequireOnce = new Libraries
%>

Uso: -

With RequireOnce 
    .Include "aClass",        "instance"
    .Include "Database",      "DataAccess"
    .Include "Constants",     "Constant"
    .Include "LoginCheck",    "Login"
End With
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top