From: Richard B. <rb...@us...> - 2005-02-10 22:42:23
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23558 Modified Files: Tag: v2_0 CCacheEntry.vb CInjectedObject.vb CPersistenceBroker.vb CPersistentObject.vb Log Message: Ensure that collections are deep copied not reference copied when persistent objects are copied (ie in the cache, and via the copy method). Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.89.2.1 retrieving revision 1.89.2.2 diff -u -d -r1.89.2.1 -r1.89.2.2 --- CPersistenceBroker.vb 6 Feb 2005 02:48:36 -0000 1.89.2.1 +++ CPersistenceBroker.vb 10 Feb 2005 22:42:11 -0000 1.89.2.2 @@ -1831,6 +1831,28 @@ End Function + Public Function ProcessPureSQL(ByVal inSQL As String, ByVal conn As _CConnection) As CCursor + Dim statement As New CSqlStatement + statement.SqlString = inSQL + + Try + PCSQLHits.Increment() + Catch + End Try + + Dim cursor As CCursor + Dim rs As CResultset + rs = conn.processSelectStatement(statement) + + cursor = New CCursor + cursor.ParentCriteria = Nothing + cursor.ResultSet = rs + cursor.ClassMap = Nothing + cursor.HoldsProxies = False + Return cursor + End Function + + '''----------------------------------------------------------------------------- ''' <summary> ''' Initiates a transaction on all database connections. @@ -2948,4 +2970,52 @@ vbCrLf & ex.Message) End Try End Sub + + Public Shared Sub CopyCollections(ByVal fromObject As IPersistableObject, ByRef toObject As IPersistableObject) + Dim t, iEnumerableType, iListType, iDicType As Type + Dim coll, collItem As Object + Dim il As IList + Dim id As IDictionary + Dim f, fields() As FieldInfo + Dim value As Object + + t = fromObject.GetObjectType + fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + For Each f In fields + iListType = f.FieldType.GetInterface("IList", True) + iDicType = f.FieldType.GetInterface("IDictionary", True) + If Not iListType Is Nothing OrElse Not iDicType Is Nothing Then + Dim ICloneType As Type = f.FieldType.GetInterface("ICloneable", True) + If Not ICloneType Is Nothing Then + 'Getting the ICloneable interface from the object. + If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + Dim IClone As ICloneable = CType(f.GetValue(fromObject.GetSourceObject), ICloneable) + coll = IClone.Clone() + Else + coll = Nothing + End If + Else + If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + 'If the field doesn't support the ICloneable interface then just set it. + coll = Activator.CreateInstance(f.FieldType) + 'need to copy references one-by-one + If Not iListType Is Nothing Then + il = CType(coll, IList) + For Each collItem In f.GetValue(fromObject.GetSourceObject) + il.Add(collItem) + Next + Else + id = CType(coll, IDictionary) + For Each de As DictionaryEntry In f.GetValue(fromObject.GetSourceObject) + id.Add(de.Key, de.Value) + Next + End If + Else + coll = Nothing + End If + End If + f.SetValue(toObject, coll) + End If + Next + End Sub End Class \ No newline at end of file Index: CCacheEntry.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCacheEntry.vb,v retrieving revision 1.25.2.2 retrieving revision 1.25.2.3 diff -u -d -r1.25.2.2 -r1.25.2.3 --- CCacheEntry.vb 6 Feb 2005 02:48:36 -0000 1.25.2.2 +++ CCacheEntry.vb 10 Feb 2005 22:42:11 -0000 1.25.2.3 @@ -123,14 +123,21 @@ End Sub Public Sub CopyCollections() - Dim t, iEnumerableType, iListType, iDicType As Type Dim coll, obj As Object + Dim t, iEnumerableType, iListType, iDicType As Type + Dim coll, obj As Object Dim il As IList Dim id As IDictionary Dim f, fields() As FieldInfo Dim value As Object - 'We must precopy this collection into the collection copy 'A simple assignment would just copy a reference to the colletion, while 'we need to copy the collection itself, so that adding/removing elements 'of the original won't effect the copy - m_collectionCollection = New Specialized.HybridDictionary t = m_object.GetObjectType + 'We must precopy this collection into the collection copy + 'A simple assignment would just copy a reference to the colletion, while + 'we need to copy the collection itself, so that adding/removing elements + 'of the original won't effect the copy + + m_collectionCollection = New Specialized.HybridDictionary + + t = m_object.GetObjectType fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) For Each f In fields iListType = f.FieldType.GetInterface("IList", True) @@ -148,7 +155,8 @@ Else If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then 'If the field doesn't support the ICloneable interface then just set it. - coll = Activator.CreateInstance(f.FieldType) 'need to copy references one-by-one + coll = Activator.CreateInstance(f.FieldType) + 'need to copy references one-by-one If Not iListType Is Nothing Then il = CType(coll, IList) For Each obj In f.GetValue(m_object.GetSourceObject) @@ -164,19 +172,26 @@ coll = Nothing End If End If - m_collectionCollection.Add(f.Name, coll) End If Next + m_collectionCollection.Add(f.Name, coll) + End If + Next End Sub Public Sub RestoreCollections() - Dim t, iEnumerableType, iListType, iDicType As Type Dim f, fields() As FieldInfo + Dim t, iEnumerableType, iListType, iDicType As Type + Dim f, fields() As FieldInfo + t = m_object.GetObjectType fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) For Each f In fields iListType = f.FieldType.GetInterface("IList", True) iDicType = f.FieldType.GetInterface("IDictionary", True) - 'iEnumerableType = f.FieldType.GetInterface("IEnumerable", True) If Not iListType Is Nothing OrElse Not iDicType Is Nothing Then - 'We must restore this collection from the collection copy 'Just use a straight value assignment - no need to worry about cloning f.SetValue(m_object.GetSourceObject, m_collectionCollection.Item(f.Name)) End If Next + 'We must restore this collection from the collection copy + 'Just use a straight value assignment - no need to worry about cloning + f.SetValue(m_object.GetSourceObject, m_collectionCollection.Item(f.Name)) + End If + Next End Sub Public Sub New(ByVal lifetime As Double) Index: CInjectedObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObject.vb,v retrieving revision 1.9.2.1 retrieving revision 1.9.2.2 diff -u -d -r1.9.2.1 -r1.9.2.2 --- CInjectedObject.vb 4 Feb 2005 04:46:08 -0000 1.9.2.1 +++ CInjectedObject.vb 10 Feb 2005 22:42:11 -0000 1.9.2.2 @@ -550,12 +550,11 @@ End Function Public Function Copy() As IPersistableObject Implements IPersistableObject.Copy - 'Dim m_object2 As Object Dim injobj As CInjectedObject injobj = CType(Me.MemberwiseClone, CInjectedObject) - 'm_object2 = Activator.CreateInstance(m_object.GetType) - 'ReplaceValues(m_object, m_object2) - 'injobj = New CInjectedObject(m_object2) + 'Because memberwise clone only reference copies collections we should also + 'copy the collections as well, since failing to do so can corrupt the cache. + CPersistenceBroker.CopyCollections(Me, injobj) Return injobj End Function Index: CPersistentObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentObject.vb,v retrieving revision 1.52 retrieving revision 1.52.2.1 diff -u -d -r1.52 -r1.52.2.1 --- CPersistentObject.vb 17 Dec 2004 03:29:01 -0000 1.52 +++ CPersistentObject.vb 10 Feb 2005 22:42:13 -0000 1.52.2.1 @@ -1224,7 +1224,12 @@ ''' </history> '''----------------------------------------------------------------------------- Public Overridable Function Copy() As IPersistableObject Implements IPersistentObject.Copy - Return Me.MemberwiseClone + Dim obj As CPersistentObject + obj = CType(Me.MemberwiseClone, CPersistentObject) + 'Because memberwise clone only reference copies collections we should also + 'copy the collections as well, since failing to do so can corrupt the cache. + CPersistenceBroker.CopyCollections(Me, obj) + Return obj End Function '''----------------------------------------------------------------------------- |