문제
ASP Classic에는 PHP의 "포함 된 한 번"기능과 동등한 기능이 있습니까?
해결책
나는 이것이 오래된 주제라는 것을 알고 있지만 누군가가 관심을 가질 경우 2 센트를 추가 할 것이라고 생각했습니다.
나는 당신이 원하는 것을 정확하게하는 함수를 썼습니다. 주어진 파일을 몇 번이나 호출하든 정확히 하나를 포함합니다.
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
메모:
- 이것은 기본 속성으로 시뮬레이션 된 가짜 기능을 사용합니다. 이것이 당신을 귀찮게한다면, 그것은 쉽게 재현 할 수 있습니다.
사전은 모든 내용을 통해 지속적이어야하는 반면, FSO는 단지 재구성을 피할뿐입니다. 가져 오기가 완료된 후에 보관한다는 아이디어가 마음에 들지 않으면 클래스를 수정하여 다음과 같이 구문을 얻을 수 있습니다.
with new Importer .import "foo" .import "bar/baz" end with
다른 팁
아뇨. 죄송합니다. 당신은 자신을 포함해야합니다.
이것은 레거시 ASP 앱을 물려받은 후 처음으로 실행 한 문제 중 하나였습니다. 내 솔루션은 현재 'app-init.asp'라는 파일에 모든 유전자 라이브러리 파일을 포함합니다. 그런 다음이 파일은 모든 페이지에 포함되어 있으며 앱 넓은 기능을 연결하기위한 단일 입력 지점과 빌드 할 기반을 제공합니다.
당신의 코드에 대한 Thom Smith에게 감사드립니다.
UTF8 소스 파일을 처리하기 위해 귀하의 버전 아래로 (및 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,"<","<") & "</tt></pre>"
Response.End
End if
On Error Goto 0
End If
End Property
End Class
Set IncludeOnce = new IncludeOnceClass
보시다시피, 나는 스트림을 닫지 않기 위해 스트림을 닫지 않습니다.
업데이트: 경로는 사례 둔감 이므로이 버전은 사전에 키로 추가하기 전에 소문자로 변환합니다. 또한 추가됩니다 ~ 전에 포함 루프 (재귀)의 경우 중복 평가를 방지하기위한 코드 평가 :
주어진 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
사전에 아직 등록되지 않은 경우 중복 평가가 발생합니다. 이 업데이트는 문제를 해결합니다.
당신이 할 수있는 최선은 SSI를 사용하여 파일을 포함하는 것입니다.
ExecuteGlobal을 사용하여 답변에 대한 경고로; vbscript가 쓰레기를 수집하거나 관리하지 않기 때문에 ExecuteGlobal은 불안정성을 생성한다고 생각합니다. 올바르게 폐기되지 않은 개체를 재정의하기 때문에 "치명적인 실패"또는 "ASP 0240 스크립트 엔진 예외"오류를 던질 수 있습니다.
따라서이를 사용하려면 소멸자가 포함 된 클래스를 포함시켜야하며 포함은 클래스의 인스턴스를 생성하고 사전에서 객체 이름을 지속 시키며 ImportFunction Destructor는 사전의 모든 객체를 파괴해야합니다.
포함은 ASP 태그 < % %>로 접두사를 접두사하지 않아야하지만 #include를 사용하면 필요합니다.
또한 executeGlobal은 모든 x = y를 할당으로 간주하고 비교가 아니라는 점에 유의해야합니다.
ismatch = (x = y) '는 가짜 결과를 일으킬 수 있습니다.
예제는 다음과 같습니다.
Class aClass
Public Sub doSomething()
...
End Sub
End Class
Dim instance
Set instance = new aClass
위의 것과 유사한 예제를 만들었지 만 포함을 서브 또는 속성 할당에 전달하는 두 번째 스타일을 사용했습니다.
그것이하는 일은, 사전의 모든 물체를 자체 소멸자로 파괴하여 쓰레기 수집을 시도하는 것입니다. 또한 포장 한 라이브러리의 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'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
%>
용법: -
With RequireOnce
.Include "aClass", "instance"
.Include "Database", "DataAccess"
.Include "Constants", "Constant"
.Include "LoginCheck", "Login"
End With