Consolidated ASP Classic MVC framework from best components
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
6.1KB

  1. <%
  2. '=======================================================================================================================
  3. ' AUTOMAPPER CLASS
  4. '=======================================================================================================================
  5. 'Side Effects: Since src and target are passed ByRef to reduce unnecessary copying, if src is a recordset then the
  6. ' current record pointer is modified using src.MoveFirst and src.MoveNext. The end result is the current
  7. ' record pointer ends the operation at src.EOF.
  8. Class Automapper_Class
  9. Private m_src
  10. Private m_target
  11. Private m_statements
  12. Private m_statements_count
  13. Private Property Get Src : set Src = m_src : End Property
  14. Private Property Get Target : set Target = m_target : End Property
  15. Private Sub Class_Initialize
  16. m_statements_count = -1
  17. ReDim m_statements(-1)
  18. End Sub
  19. Private Sub ResetState
  20. m_statements_count = -1
  21. ReDim m_statements(-1)
  22. Set m_src = Nothing
  23. Set m_target = Nothing
  24. End Sub
  25. 'Maps all rs or object fields to corresponding fields in the specified class.
  26. Public Function AutoMap(src_obj, target_obj)
  27. Set AutoMap = FlexMap(src_obj, target_obj, empty)
  28. End Function
  29. 'Only maps fields specified in the field_names array (array of strings).
  30. 'If field_names is empty, attempts to map all fields from the passed rs or object.
  31. Public Function FlexMap(src_obj, target_obj, field_names)
  32. Set FlexMap = DynMap(src_obj, target_obj, field_names, empty)
  33. End Function
  34. 'Only maps fields specified in the field_names array (array of strings).
  35. 'If field_names is empty then src MUST be a recordset as it attempts to map all fields from the recordset.
  36. 'Since there is no reflection in vbscript, there is no way around this short of pseudo-reflection.
  37. Public Function DynMap(src_obj, target_obj, field_names, exprs)
  38. SetSource src_obj
  39. SetTarget target_obj
  40. dim field_name
  41. dim field_idx 'loop counter
  42. if IsEmpty(field_names) then 'map everything
  43. if typename(src_obj) = "Recordset" then
  44. for field_idx = 0 to src_obj.Fields.Count - 1
  45. field_name = src_obj.Fields.Item(field_idx).Name
  46. 'AddStatement field_name
  47. AddStatement BuildStatement(field_name)
  48. next
  49. elseif InStr(typename(src_obj), "Dictionary") > 0 then 'enables Scripting.Dictionary and IRequestDictionary for Request.Querystring and Request.Form
  50. for each field_name in src_obj
  51. AddStatement BuildStatement(field_name)
  52. next
  53. elseif not IsEmpty(src_obj.Class_Get_Properties) then
  54. dim props : props = src_obj.Class_Get_Properties
  55. for field_idx = 0 to ubound(props)
  56. field_name = props(field_idx)
  57. 'AddStatement field_name
  58. AddStatement BuildStatement(field_name)
  59. next
  60. else 'some invalid type of object
  61. Err.Raise 9, "Automapper.DynMap", "Cannot automatically map this source object. Expected recordset or object implementing Class_Get_Properties reflection, got: " & typename(src_obj)
  62. end if
  63. else 'map only specified fields
  64. for field_idx = lbound(field_names) to ubound(field_names)
  65. field_name = field_names(field_idx)
  66. 'AddStatement field_name
  67. AddStatement BuildStatement(field_name)
  68. next
  69. end if
  70. dim exprs_idx
  71. if not IsEmpty(exprs) then
  72. if typename(exprs) = "Variant()" then
  73. for exprs_idx = lbound(exprs) to ubound(exprs)
  74. 'field_name = exprs(exprs_idx)
  75. 'AddStatement field_name
  76. AddStatement exprs(exprs_idx)
  77. next
  78. else 'assume string or string-like default value
  79. AddStatement exprs
  80. end if
  81. end if
  82. 'Can't pre-join the statements because if one fails the rest of them fail too... :(
  83. 'dim joined_statements : joined_statements = Join(m_statements, " : ")
  84. 'put joined_statements
  85. 'suspend errors to prevent failing when attempting to map a field that does not exist in the class
  86. on error resume next
  87. dim stmt_idx
  88. for stmt_idx = 0 to ubound(m_statements)
  89. Execute m_statements(stmt_idx)
  90. next
  91. on error goto 0
  92. set DynMap = m_target
  93. ResetState
  94. End Function
  95. Private Sub SetSource(ByVal src_obj)
  96. set m_src = src_obj
  97. End Sub
  98. Private Sub SetTarget(ByVal target_obj)
  99. if typename(target_obj) = "String" then
  100. set m_target = eval("new " & target_obj)
  101. else
  102. set m_target = target_obj
  103. end if
  104. End Sub
  105. 'Builds a statement and adds it to the internal statements array
  106. Private Sub AddStatement(ByVal stmt)
  107. m_statements_count = m_statements_count + 1
  108. ReDim Preserve m_statements(m_statements_count)
  109. m_statements(m_statements_count) = stmt
  110. End Sub
  111. Private Function BuildStatement(ByVal field_name)
  112. dim result
  113. if typename(m_src) = "Recordset" or InStr(typename(m_src), "Dictionary") > 0 then
  114. result = "m_target." & field_name & " = m_src(""" & field_name & """)"
  115. else
  116. 'Funky magic...
  117. 'If src.field_name is an object, ensure the set statement is used
  118. if IsObject(eval("m_src." & field_name)) then
  119. result = "set "
  120. else
  121. 'result = "m_target." & field_name & " = m_src." & field_name
  122. end if
  123. result = result & " m_target." & field_name & " = m_src." & field_name
  124. end if
  125. BuildStatement = result
  126. End Function
  127. End Class
  128. Function Automapper()
  129. Set Automapper = new Automapper_Class
  130. End Function
  131. %>

Powered by TurnKey Linux.