ASP Classic的功能是否相当于PHP的“包含一次”功能?
答案 0 :(得分:13)
我知道这是一个古老的话题,但我想我会加上我的两分钱,以防任何人有兴趣。
我编写了一个能够完全按照你想要的方式运行的函数:无论调用它多少次,都包含给定的文件。
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
答案 1 :(得分:4)
没有。抱歉。你必须管理包括你自己。
答案 2 :(得分:2)
这是我继承遗留ASP应用程序后首次遇到的问题之一。我的解决方案目前是将所有genric库文件包含在名为“app-init.asp”的文件中。然后,此文件将包含在所有页面中,并为您提供一个单一的入口点,以连接应用程序范围的功能和构建的基础。
答案 3 :(得分:2)
感谢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
尚未在字典中注册,则第二个{{1}}将发生重复评估,我们不想要。此更新解决了此问题。
答案 4 :(得分:1)
您可以做的最好的事情是使用SSI来包含文件:
答案 5 :(得分:1)
使用ExecuteGlobal作为答案的警告;我认为ExecuteGlobal会产生不稳定性,因为VBScript不会很好地收集或管理内存。它可能会导致“灾难性故障”或“ASP 0240脚本引擎异常”错误,因为您正在重新定义未正确处理的对象。
因此,要使用它,您还需要使您的包含,具有析构函数的类和包含应该创建类的实例,在字典中保留对象名称,并且ImportFunction析构函数应该销毁所有对象。字典。
包含不应以ASP标记为前缀&lt; %%&gt;或者,使用#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'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
答案 6 :(得分:0)
这是将文件包含到Asp Classic中的方法。
包含此文件,它看起来会灰显,但包含文件。