ASP 에서 동적 대상 을 만 드 는 공장 클래스(PHP 와 유사 한 stdClass)

최근 에 ASP/VBScript 코드 를 정리 한 결과 과거의 ASP 가 실현 한 MVC 프레임 워 크 를 발 견 했 습 니 다.안 타 깝 게 도 반제품 이 고 효율 도 문제 가 되 었 습 니 다.그런데 안에 제 가 쓴 코드 가 있 는 것 을 발 견 했 습 니 다.사람 을 만 날 수 있 을 것 같 아서 오늘 이 글 을 썼 습 니 다.
ASP 라 고 해도 VBScript 과 관련 이 없다.VBScript 언어 는 Visual Basic 에 전승 되 었 고 VB 의 문법 유연성 이 만 족 스 럽 지 못 하 다.VBS 는 그 부분 집합 으로 짐작 할 수 있다.신마 반사,자성 등 선진 적 인 기술 은 마이크로소프트 가.NET 에서 야 도입 되 었 다.버 려 진 기술 로 서 마이크로소프트 가 지원 해 주 기 를 바라 지 않 기 때문에 완고 하고 보수적인 프로 그 래머 는 비슷 한 기능 을 모방 하기 위해 머리 를 쥐 어 짜 야만 한다.
좋 습 니 다.저 는 오랫동안 완고한 수구파 중의 한 사람 이 었 다 는 것 을 인정 합 니 다.오늘 소개 한 것 은 바로 그 중의 한 가지 기능 입 니 다.동태 적 으로 속성 대상 을 만 들 고 속성 대상 을 우선 이렇게 부 릅 니 다.즉,동태 적 으로 만 든 대상 은 속성(Properties)만 포함 합 니 다.
다음은 여러분 이 참고 할 수 있 도록 실현 코드 를 붙 입 니 다.

'
' ASP/VBScript Dynamic Object Generator
' Author: WangYe
' For more information please visit
'    
' This code is distributed under the BSD license
'
Const PROPERTY_ACCESS_READONLY = 1
Const PROPERTY_ACCESS_WRITEONLY = -1
Const PROPERTY_ACCESS_ALL = 0

Class DynamicObject
    Private m_objProperties
    Private m_strName

    Private Sub Class_Initialize()
        Set m_objProperties = CreateObject("Scripting.Dictionary")
        m_strName = "AnonymousObject"
    End Sub

    Private Sub Class_Terminate()
        If Not IsObject(m_objProperties) Then
            m_objProperties.RemoveAll
        End If
        Set m_objProperties = Nothing
    End Sub

    Public Sub setClassName(strName)
        m_strName = strName
    End Sub

    Public Sub add(key, value, access)
        m_objProperties.Add key, Array(value, access)
    End Sub

    Public Sub setValue(key, value, access)
        If m_objProperties.Exists(key) Then
            m_objProperties.Item(key)(0) = value
            m_objProperties.Item(key)(1) = access
        Else
            add key,value,access
        End If
    End Sub

    Private Function getReadOnlyCode(strKey)
        Dim strPrivateName, strPublicGetName
        strPrivateName = "m_var" & strKey
        strPublicGetName = "get" & strKey
        getReadOnlyCode = _
            "Public Function " & strPublicGetName & "() :" & _
            strPublicGetName & "=" & strPrivateName & " : " & _
            "End Function : Public Property Get " & strKey & _
            " : " & strKey & "=" & strPrivateName & " : End Property : "
    End Function

    Private Function getWriteOnlyCode(strKey)
        Dim pstr
        Dim strPrivateName, strPublicSetName, strParamName
        strPrivateName = "m_var" & strKey
        strPublicSetName = "set" & strKey
        strParamName = "param" & strKey
        getWriteOnlyCode = _
            "Public Sub " & strPublicSetName & "(" & strParamName & ") :" & _
            strPrivateName & "=" & strParamName & " : " & _
            "End Sub : Public Property Let " & strKey & "(" & strParamName & ")" & _
            " : " & strPrivateName & "=" & strParamName & " : End Property : "
    End Function

    Private Function parse()
        Dim i, Keys, Items
        Keys = m_objProperties.Keys
        Items = m_objProperties.Items

        Dim init, pstr
        init = ""
        pstr = ""
        parse = "Class " & m_strName & " :" & _
                "Private Sub Class_Initialize() : "

        Dim strPrivateName
        For i = 0 To m_objProperties.Count - 1
            strPrivateName = "m_var" & Keys(i)
            init = init & strPrivateName & "=""" & _
                Replace(CStr(Items(i)(0)), """", """""") & """:"
            pstr = pstr & "Private " & strPrivateName & " : "
            If CInt(Items(i)(1)) > 0 Then ' ReadOnly
                pstr = pstr & getReadOnlyCode(Keys(i))
            ElseIf CInt(Items(i)(1)) < 0 Then ' WriteOnly
                pstr = pstr & getWriteOnlyCode(Keys(i))
            Else ' AccessAll
                pstr = pstr & getReadOnlyCode(Keys(i)) & _
                        getWriteOnlyCode(Keys(i))
            End If
        Next
        parse = parse & init & "End Sub : " &  pstr & "End Class"
    End Function

    Public Function getObject()
        Call Execute(parse)
        Set getObject = Eval("New " & m_strName)
    End Function

    Public Sub invokeObject(ByRef obj)
        Call Execute(parse)
        Set obj = Eval("New " & m_strName)
    End Sub
End Class
속성 대상 에 대해 각각 Property 직접 방문 모드 와 set 또는 get 함수 방문 모드 를 제공 합 니 다.물론 저 는 세 가지 권한 통 제 를 제 공 했 습 니 다.add 방법 에서 사용 합 니 다.각각 PROPERTY 입 니 다.ACCESS_READOLLY(속성 만 읽 기),PROPERTYACCESS_WRITEONLY(속성 만 쓰기)와 PROPERTYACCESS_ALL(속성 읽 기와 쓰기)은 다음 과 같이 사용 할 수 있 습 니 다.(하나의 예)

Dim DynObj
Set DynObj = New DynamicObject
    DynObj.add "Name", "WangYe", PROPERTY_ACCESS_READONLY
    DynObj.add "HomePage", "http://jb51.net", PROPERTY_ACCESS_READONLY
    DynObj.add "Job", "Programmer", PROPERTY_ACCESS_ALL
    '
    ' setClassName,
    ' AnonymousObject
    ' ,
    '
    DynObj.setClassName "User"

    Dim User
    Set User = DynObj.GetObject()
    ' DynObj.invokeObject User
        Response.Write User.Name
        ' Response.Write User.getName()
 Response.Write User.HomePage
        ' Response.Write User.getHomePage()
 Response.Write User.Job
        ' Response.Write User.getJob()

        '
        User.Job = "Engineer"
        ' User.setJob "Engineer"

        Response.Write User.getJob()
    Set User = Nothing

Set DynObj = Nothing

그 원 리 는 간단 합 니 다.주어진 Key-Value 를 통 해 VBS Class 스 크 립 트 코드 를 동적 으로 생 성 한 다음 에 이 코드 를 코드 컨 텍스트 흐름 에 추가 하고 마지막 으로 Eval 을 통 해 이 대상 을 새로 만 드 는 것 입 니 다.
자,여기까지 소개 하 겠 습 니 다.앞으로 클래식 ASP 와 관련 된 기술 코드 를 계속 공개 할 것 같 습 니 다.
2012 년 11 월 7 일 업데이트
오래된 프로젝트 에서 이 식 된 버그 를 복구 하 다.
버그 를 복구 하고 특성 을 추 가 했 습 니 다.제 가 먼저 최신 코드 를 붙 여서 여러분 께 참고 하도록 하 겠 습 니 다.
'
' ASP/VBScript Dynamic Object Generator
' Author: WangYe
' For more information please visit
'    
' This code is distributed under the BSD license
'
' UPDATE:
'   2012/11/7
'       1. Add variable key validator.
'       2. Add hasattr_ property for determine
'          if the property exists.
'       3. Add getattr_ property for get property
'          value safety.
'       4. Class name can be accessed by ClassName_ property.
'       5. Fixed some issues.
'
Const PROPERTY_ACCESS_READONLY = 1
Const PROPERTY_ACCESS_WRITEONLY = -1
Const PROPERTY_ACCESS_ALL = 0

Class DynamicObject
    Private m_objProperties
    Private m_strName
    Private m_objRegExp

    Private Sub Class_Initialize()
        Set m_objProperties = CreateObject("Scripting.Dictionary")
        Set m_objRegExp = New RegExp
            m_objRegExp.IgnoreCase = True
            m_objRegExp.Global = False
            m_objRegExp.Pattern = "^[a-z][a-z0-9]*$"
        m_strName = "AnonymousObject"
        m_objProperties.Add "ClassName_", _
            Array(m_strName, PROPERTY_ACCESS_READONLY)
    End Sub

    Private Sub Class_Terminate()
        Set m_objRegExp = Nothing
        If IsObject(m_objProperties) Then
            m_objProperties.RemoveAll
        End If
        Set m_objProperties = Nothing
    End Sub

    Public Sub setClassName(strName)
        If Not m_objRegExp.Test(strName) Then
            ' Skipped Invalid Class Name
            ' Raise
            Exit Sub
        End If
        m_strName = strName
        m_objProperties("ClassName_") = _
            Array(m_strName, PROPERTY_ACCESS_READONLY)
    End Sub

    Public Sub add(key, value, access)
        If Not m_objRegExp.Test(key) Then
            ' Skipped Invalid key
            ' Raise
            Exit Sub
        End If
        If key = "hasattr_" Then key = "hasattr__"
        If key = "ClassName_" Then key = "ClassName__"
        'Response.Write key
        m_objProperties.Add key, Array(value, access)
    End Sub

    Public Sub setValue(key, value, access)
        If m_objProperties.Exists(key) Then
            m_objProperties.Item(key)(0) = value
            m_objProperties.Item(key)(1) = access
        Else
            add key,value,access
        End If
    End Sub

    Private Function getReadOnlyCode(strKey)
        Dim strPrivateName, strPublicGetName
        strPrivateName = "m_var" & strKey
        strPublicGetName = "get" & strKey
        getReadOnlyCode = _
            "Public Function " & strPublicGetName & "() :" & _
            strPublicGetName & "=" & strPrivateName & " : " & _
            "End Function : Public Property Get " & strKey & _
            " : " & strKey & "=" & strPrivateName & _
            " : End Property : "
    End Function

    Private Function getWriteOnlyCode(strKey)
        Dim pstr
        Dim strPrivateName, strPublicSetName, strParamName
        strPrivateName = "m_var" & strKey
        strPublicSetName = "set" & strKey
        strParamName = "param" & strKey
        getWriteOnlyCode = _
            "Public Sub " & strPublicSetName & _
            "(" & strParamName & ") :" & _
            strPrivateName & "=" & strParamName & " : " & _
            "End Sub : Public Property Let " & strKey & _
            "(" & strParamName & ")" & _
            " : " & strPrivateName & "=" & strParamName & _
            " : End Property : "
    End Function

    Private Function parse()
        Dim i, Keys, Items
        Keys = m_objProperties.Keys
        Items = m_objProperties.Items

        Dim init, pstr
        init = ""
        pstr = ""
        parse = "Class " & m_strName & " :" & _
                "Private Sub Class_Initialize() : "

        Dim strPrivateName, strAvailableKeys

        For i = 0 To m_objProperties.Count - 1
            strPrivateName = "m_var" & Keys(i)
            init = init & strPrivateName & "=""" & _
                Replace(CStr(Items(i)(0)), """", """""") & """:"
            pstr = pstr & "Private " & strPrivateName & " : "
            strAvailableKeys = strAvailableKeys & Keys(i) & ","
            If CInt(Items(i)(1)) > 0 Then ' ReadOnly
                pstr = pstr & getReadOnlyCode(Keys(i))
            ElseIf CInt(Items(i)(1)) < 0 Then ' WriteOnly
                pstr = pstr & getWriteOnlyCode(Keys(i))
            Else ' AccessAll
                pstr = pstr & getReadOnlyCode(Keys(i)) & _
                        getWriteOnlyCode(Keys(i))
            End If
        Next

        init = init & "m_strAvailableKeys = Replace(""," & _
                strAvailableKeys & """, "" "", """") : "
        Dim hasstmt
        hasstmt = "Private m_strAvailableKeys : " & _
                  "Public Function hasattr_(ByVal key) : " & _
                  "hasattr_ = CBool(InStr(m_strAvailableKeys," & _
                  " "","" & key & "","") > 0) : " & _
                  "End Function : " & _
                  "Public Function getattr_(ByVal key, ByVal defaultValue) : " & _
                  "If hasattr_(key) Then : getattr_ = Eval(key) : " & _
                  "Else : getattr_ = defaultValue : End If : " & _
                  "End Function : "

        parse = parse & init & "End Sub : " & _
            hasstmt & pstr & "End Class"
    End Function

    Public Function getObject()
        'Response.Write parse
        Call Execute(parse)
        Set getObject = Eval("New " & m_strName)
    End Function

    Public Sub invokeObject(ByRef obj)
        Call Execute(parse)
        Set obj = Eval("New " & m_strName)
    End Sub
End Class
주의해 야 할 몇 가지 새로운 기능:
1.유형 명 과 속성 명 검증 조 치 를 추가 하여 기형 적 인 유형 명 이나 속성 명 으로 인해 동적 으로 생 성 된 코드 에 문법 오류 가 발생 하 는 것 을 방지 합 니 다.그러나 처리 방식 은 무시 하 는 것 입 니 다.Raise 이상 을 생각 했 지만 VBS 가 이상 처리 에 좋 지 않 은 것 을 고려 하여 무시 전략 을 취 합 니 다.
'유효한 클래스 이름 이나 속성 명 은 알파벳 으로 시작 해 야 합 니 다
Dim DynObj
Set DynObj = New DynamicObject
    DynObj.setClassName "1User" ' ,
    ' ,
    DynObj.add "%Name", "WangYe", PROPERTY_ACCESS_READONLY
Set DynObj = Nothing
2.동적 대상 에 hasattr 를 추 가 했 습 니 다.방법,이 속성 은 이 대상 이 해당 하 는 속성 을 지원 하 는 지 검사 하 는 데 사 용 됩 니 다.하나의 속성 에 접근 하기 전에 이 대상 이 이 속성 을 지원 하 는 지 확인 할 수 있 습 니 다

Dim DynObj
Set DynObj = New DynamicObject
    DynObj.add "Name", "WangYe", PROPERTY_ACCESS_READONLY

    Response.Write DynObj.hasattr_("Name") ' True
    Response.Write DynObj.hasattr_("Favor") ' False

Set DynObj = Nothing

3.동적 대상 에 getattr 추가방법,이 방법 은 지정 한 속성 값 을 안전하게 가 져 올 수 있 습 니 다.대상 에 속성 값 이 존재 하지 않 아 오류 가 발생 하지 않도록 합 니 다.방법 원형 은 getattr (ByVal propertyName,ByVal defaultValue),인자 propertyName 이 지정 한 속성의 이름,defaultValue 는 지정 한 속성 이 존재 하지 않 을 때 되 돌 릴 수 있 는 기본 값 입 니 다.예 를 들 어 다음 코드:

Dim DynObj
Set DynObj = New DynamicObject
    DynObj.add "Name", "WangYe", PROPERTY_ACCESS_READONLY

    Response.Write DynObj.getattr_("Name", "N/A") ' WangYe
    Response.Write DynObj.getattr_("Favor", "N/A") ' N/A

Set DynObj = Nothing

4.동적 대상 의 클래스 이름 은 ClassName속성 또는 getClassName ()방법 획득.
2012 년 11 월 12 일 업데이트
따옴표 복구 로 구조 류 오류 가 발생 하거나 임의의 코드 를 실행 하 는 bug.

좋은 웹페이지 즐겨찾기