Подтвердить что ты не робот

Asp Classic Include Once

Есть ли у ASP Classic функция, эквивалентная функции PHP "включить один раз"?

4b9b3361

Ответ 1

Я знаю, что это старая тема, но я думал, что добавлю свои два цента на тот случай, если кто-то заинтересован.

Я написал функцию, которая делает именно то, что вы хотите: включает данный файл ровно один, независимо от того, сколько раз он был вызван.

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

Примечания:

  • Здесь используется функция faux, смоделированная с использованием свойства default. Если это вас беспокоит, оно легко реорганизуется.
  • Словарь должен быть постоянным через все включает, тогда как сохранение fso просто предотвращает его восстановление. Если вам не нравится идея сохранить их после завершения импорта, вы можете изменить класс, чтобы получить синтаксис следующим образом:

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

Ответ 2

Нет. Сожалею. Вы должны управлять собой.

Ответ 3

Это была одна из проблем, с которой я впервые столкнулся после наследования устаревшего ASP-приложения. Мое решение в настоящее время включает все файлы библиотеки genric в файл под названием "app-init.asp". Этот файл затем включается во все страницы и дает вам одну точку входа для подключения расширенной функциональности приложения и базы для построения.

Ответ 5

Спасибо Тому Смиту за ваш фрагмент кода.

Ниже версии, основанной на вашем, для обработки исходных файлов UTF8 (и кто управляет открытием и закрытием тегов ASP).

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), "tlout"
            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

Как вы видите, я не закрываю поток, чтобы продолжить обработку.

Обновление:. Поскольку пути нечувствительны к регистру, эта версия преобразует их в нижний регистр перед добавлением в словарь как ключи. Кроме того, они добавлены до оценки кода, чтобы предотвратить дублирование оценок в случае цикла включения (recursion):

Данные A.asp и B.asp:

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

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

Так как A еще не оценивается вообще при включении кода B, второй IncludeOnce будет иметь повторяющуюся оценку, если он еще не зарегистрирован в словаре, чего мы не хотим. Это обновление устраняет проблему.

Ответ 6

Как предостережение к Ответу с использованием ExecuteGlobal; Я думаю, что ExecuteGlobal создает нестабильность, поскольку VBScript не мусор собирает и не управляет памятью. Он может вызывать ошибки "Катастрофический сбой" или "ASP 0240 Script Engine Exception", поскольку вы переопределяете объект, который не был правильно удален.

Итак, чтобы использовать это, вам также необходимо будет включить ваши классы, классы, у которых есть деструкторы, и include должны создать экземпляр класса, сохранить имя объекта в словаре, а destructor ImportFunction должен уничтожить все объекты в словарь.

Включить не следует с префиксом ASP-тегов <%% > , тогда как с помощью #include вам нужно будет.

Следует также отметить, что ExecuteGlobal считает, что все X = Y являются назначением, а не сравнением, поэтому: -

isMatch = (X = Y) 'может создавать ложные результаты.

Пример: -

Class aClass

    Public Sub doSomething()
        ...
    End Sub

End Class

Dim instance
Set instance = new aClass

Я создал пример, аналогичный приведенному выше, но используя второй стиль передачи include в Sub или присвоение свойства

То, что он также делает, это попытки сбора мусора путем уничтожения всех объектов в словаре, в своем собственном деструкторе. Он также разбивает теги asp для упакованных библиотек.

<% 
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 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 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
%>

Использование: -

With RequireOnce 
    .Include "aClass",        "instance"
    .Include "Database",      "DataAccess"
    .Include "Constants",     "Constant"
    .Include "LoginCheck",    "Login"
End With