Есть ли у ASP Classic функция, эквивалентная функции PHP "включить один раз"?
Asp Classic Include Once
Ответ 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". Этот файл затем включается во все страницы и дает вам одну точку входа для подключения расширенной функциональности приложения и базы для построения.
Ответ 4
Лучшее, что вы можете сделать, это использовать SSI для включения файлов:
Ответ 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,"<","<") & "</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