From: Richard B. <rb...@us...> - 2005-02-14 02:23:30
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23624 Modified Files: CAssociationState.vb CCacheEntry.vb CInjectedObject.vb CPersistenceBroker.vb CPersistentCollection.vb CPersistentObject.vb Log Message: Fixes for copying objects to/from the cache and updating many to many associations. Events for collections within an object are now correctly wired to the copied object during the copy instead of either being blank or remaining wired to the original object. Further fixes for cache consistency before and after transaction rollback were also made. ContainerObject property on CPersistentCollection is now marked as obsolete and will probably be removed in a future update. Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.94 retrieving revision 1.95 diff -u -d -r1.94 -r1.95 --- CPersistenceBroker.vb 11 Feb 2005 02:51:35 -0000 1.94 +++ CPersistenceBroker.vb 14 Feb 2005 02:23:10 -0000 1.95 @@ -2538,6 +2538,7 @@ Dim i, k As Integer Dim tmpObj As Object Dim aObj As CAssociationObject + Dim isNewManyToMany As Boolean If obj.IsQueued Then 'if an object has already been added to the save queue, there is no need to add @@ -2639,21 +2640,20 @@ value = tmpObj End If aObj = Nothing - state.ValidateObject(value) + isNewManyToMany = state.ValidateObject(value) For Each qObj In getObjectsToSave(value, True, checkAssociationsRecursivly) queue.Enqueue(qObj) - If aObj Is Nothing AndAlso value.Equals(qObj) Then - 'since we are saving this object (obj) and one of the objects in the association - 'we need to ensure the association table gets updated. This will be done via - 'the CAssociationObject class. We need to create an object here for the class. - aObj = New CAssociationObject - aObj.ObjectA = obj - aObj.ObjectB = value - aObj.Association = udamap - queue.Enqueue(aObj) - End If Next + If isNewManyToMany Then + 'We need to create an association object here for the class. + aObj = New CAssociationObject + aObj.ObjectA = obj + aObj.ObjectB = value + aObj.Association = udamap + queue.Enqueue(aObj) + End If Next k + 'Remove old association records for items removed from the collection state.DoCleanUp() End If End If @@ -3091,7 +3091,7 @@ 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 t, iEnumerableType, iListType, iDicType As Type Dim fromColl, toColl, collItem As Object Dim il As IList Dim id As IDictionary Dim f, fields() As FieldInfo @@ -3108,30 +3108,68 @@ '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() + toColl = IClone.Clone() Else - coll = Nothing + toColl = Nothing End If Else - If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + fromColl = f.GetValue(fromObject.GetSourceObject) + If Not fromColl 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 + t = f.FieldType + toColl = Activator.CreateInstance(t) 'need to copy references one-by-one + 'Also neeed to connect event handlers of new collection to new object based + 'on event connections of the old collection and the old object + Dim fColl, fieldsColl() As FieldInfo + Dim d, newD, delArray(), newDelArray() As [Delegate] + Dim collDel As MulticastDelegate + While Not t Is Nothing + fieldsColl = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + For Each fColl In fieldsColl + If fColl.FieldType.Name = fColl.Name & "Handler" OrElse fColl.FieldType Is GetType(EventHandler) Then + 'This is an event! + d = fColl.GetValue(fromColl) + collDel = Nothing + If Not d Is Nothing Then + delArray = d.GetInvocationList + For Each d In delArray + If Not d.Target.GetType.GetInterface("IPersistableObject") Is Nothing Then + If CType(d.Target, IPersistableObject).Equals(fromObject.GetSourceObject) Then + newD = MulticastDelegate.CreateDelegate(fColl.FieldType, toObject, d.Method.Name) + If collDel Is Nothing Then + collDel = newD + Else + collDel.Combine(collDel, newD) + End If + End If + End If + Next + fColl.SetValue(toColl, collDel) + End If + End If + Next + If t.IsSubclassOf(GetType(CPersistentCollection)) Then + t = t.BaseType + Else + t = Nothing + End If + End While If Not iListType Is Nothing Then - il = CType(coll, IList) - For Each collItem In f.GetValue(fromObject.GetSourceObject) + il = CType(toColl, IList) + For Each collItem In fromColl il.Add(collItem) Next Else - id = CType(coll, IDictionary) - For Each de As DictionaryEntry In f.GetValue(fromObject.GetSourceObject) + id = CType(toColl, IDictionary) + For Each de As DictionaryEntry In fromColl id.Add(de.Key, de.Value) Next End If Else - coll = Nothing + toColl = Nothing End If End If - f.SetValue(toObject.GetSourceObject, coll) + f.SetValue(toObject.GetSourceObject, toColl) End If Next End Sub End Class \ No newline at end of file Index: CAssociationState.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CAssociationState.vb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- CAssociationState.vb 11 Feb 2005 02:51:37 -0000 1.1 +++ CAssociationState.vb 14 Feb 2005 02:23:10 -0000 1.2 @@ -179,7 +179,7 @@ AttrMap = keys(i).AttributeMap tmpObj = Nothing Try - tmpObj = obj.GetObjectByAttribute(AttrMap.Name) + tmpObj = obj.GetValueByAttribute(AttrMap.Name) Catch ex As Exception End Try ck.Add(tmpObj) @@ -187,18 +187,23 @@ Return ck End Function - Public Sub ValidateObject(ByVal toObject As IPersistableObject) + Public Function ValidateObject(ByVal toObject As IPersistableObject) As Boolean 'Now we want to find a collection entry which has a matching key signature to the 'passed object. 'This will indicate that the association is still valid, and that we can remove + 'the from/to key pairing from the list of records to delete + ' + 'The function returns true if the object is not in the existing many-to-many association + 'ie we must add it. False indicates the association already exists. + ' If m_association Is Nothing OrElse m_fromObject Is Nothing OrElse toObject Is Nothing Then - Return + Return False End If Dim Keys As CAssociationKeys If m_fromObject.GetClassMap.Name = m_association.FromClass.Name Then - Keys = m_association.AssocationTable.FromKeys - Else Keys = m_association.AssocationTable.ToKeys + Else + Keys = m_association.AssocationTable.FromKeys End If Dim objKey As Collection = createKey(toObject, Keys) @@ -219,8 +224,10 @@ Next If found Then m_toClassKeysCollection.Remove(indexToRemove) + Return False End If - End Sub + Return True + End Function Public Sub DoCleanUp() 'Remove records for anything left in the keys collection Index: CCacheEntry.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCacheEntry.vb,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- CCacheEntry.vb 10 Feb 2005 04:22:39 -0000 1.28 +++ CCacheEntry.vb 14 Feb 2005 02:23:10 -0000 1.29 @@ -30,6 +30,7 @@ Private m_object As IPersistableObject Private m_objectCopy As IPersistableObject + Private m_objectCopyAtTransactionStart As IPersistableObject Private m_transactionType As CCacheEntry.CacheTransaction Private m_expiryTime As Date Private m_originalObject As IPersistableObject @@ -115,68 +116,77 @@ End Property Public Sub CopyObject() + 'Need two object copies + 'One for the copy made at the very start of the transaction + 'One for any updates made to the object (via save) during the transaction so that + ' cache reads get the correct copy + m_objectCopy = m_object.Copy + m_objectCopyAtTransactionStart = m_object.Copy + End Sub + + Public Sub UpdateObject() m_objectCopy = m_object.Copy End Sub Public Sub RestoreObject() - m_object = m_objectCopy - End Sub + m_object = m_objectCopyAtTransactionStart + End Sub - Public Sub CopyCollections() - 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 + ' Public Sub CopyCollections() + ' 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 - 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(m_object.GetSourceObject) Is Nothing Then - Dim IClone As ICloneable = CType(f.GetValue(m_object.GetSourceObject), ICloneable) - coll = IClone.Clone() - Else - coll = Nothing - End If - 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 - If Not iListType Is Nothing Then - il = CType(coll, IList) - For Each obj In f.GetValue(m_object.GetSourceObject) - il.Add(obj) - Next - Else - id = CType(coll, IDictionary) - For Each de As DictionaryEntry In f.GetValue(m_object.GetSourceObject) - id.Add(de.Key, de.Value) - Next - End If - Else - coll = Nothing - End If - End If - m_collectionCollection.Add(f.Name, coll) End If Next - End Sub + ' '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) + ' 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(m_object.GetSourceObject) Is Nothing Then + ' Dim IClone As ICloneable = CType(f.GetValue(m_object.GetSourceObject), ICloneable) + ' coll = IClone.Clone() + ' Else + ' coll = Nothing + ' End If + ' 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 + ' If Not iListType Is Nothing Then + ' il = CType(coll, IList) + ' For Each obj In f.GetValue(m_object.GetSourceObject) + ' il.Add(obj) + ' Next + ' Else + ' id = CType(coll, IDictionary) + ' For Each de As DictionaryEntry In f.GetValue(m_object.GetSourceObject) + ' id.Add(de.Key, de.Value) + ' Next + ' End If + ' Else + ' coll = Nothing + ' End If + ' End If + ' 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 - 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) - 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 - End Sub + 'Public Sub RestoreCollections() + ' 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) + ' 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 + 'End Sub Public Sub New(ByVal lifetime As Double) m_expiryTime = DateAdd(DateInterval.Minute, lifetime, Now) @@ -621,7 +631,6 @@ End If If obj.GetClassMap.RelationalDatabase.getConnection(Nothing).Started Then ce.TransactionType = CCacheEntry.CacheTransaction.Saved - ce.CopyObject() End If Try ce.OriginalObject = obj @@ -907,16 +916,23 @@ For Each x In Me ce = x.Value - 'Lets cancel deletes first - just means resetting transaction to None - If ce.TransactionType = CCacheEntry.CacheTransaction.Deleted AndAlso ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then - ce.TransactionType = CCacheEntry.CacheTransaction.None - ce.RestoreCollections() - End If - 'Now look for cache entries to be saved and restore them - If ce.TransactionType = CCacheEntry.CacheTransaction.Saved AndAlso ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then - ce.RestoreObject() - ce.RestoreCollections() - ce.TransactionType = CCacheEntry.CacheTransaction.None + If ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then + Select Case ce.TransactionType + Case CCacheEntry.CacheTransaction.None + 'Even though an object hasn't been saved/deleted it may still have been + 'modified so we must restore it in any case + ce.RestoreObject() + Case CCacheEntry.CacheTransaction.Deleted + 'Lets cancel deletes first - just means resetting transaction to None + ce.TransactionType = CCacheEntry.CacheTransaction.None + 'ce.RestoreCollections() + ce.RestoreObject() + Case CCacheEntry.CacheTransaction.Saved + 'Now look for cache entries to be saved and restore them + ce.RestoreObject() + 'ce.RestoreCollections() + ce.TransactionType = CCacheEntry.CacheTransaction.None + End Select End If Next @@ -940,7 +956,8 @@ For Each x In Me ce = x.Value If ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then - ce.CopyCollections() + 'ce.CopyCollections() + ce.CopyObject() End If Next End Sub Index: CInjectedObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObject.vb,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- CInjectedObject.vb 11 Feb 2005 02:51:35 -0000 1.12 +++ CInjectedObject.vb 14 Feb 2005 02:23:10 -0000 1.13 @@ -76,15 +76,19 @@ End If Dim f, fields() As FieldInfo Dim value As Object - Dim t As Type - Try + Dim t, iListType, iDicType As Type Try t = sourceObject.GetType While Not t Is Nothing fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) 'Note that this will copy event handlers as well For Each f In fields - value = f.GetValue(sourceObject) - f.SetValue(targetObject, value) + iListType = f.FieldType.GetInterface("IList", True) + iDicType = f.FieldType.GetInterface("IDictionary", True) + 'Do not copy collections yet - we'll do that at the end + If iListType Is Nothing AndAlso iDicType Is Nothing Then + value = f.GetValue(sourceObject) + f.SetValue(targetObject, value) + End If Next If Not t.BaseType Is Nothing Then t = t.BaseType @@ -92,7 +96,7 @@ t = Nothing End If End While - Catch ex As Exception + CPersistenceBroker.CopyCollections(sourceObject, targetObject) Catch ex As Exception Debug.WriteLine(ex.Message) End Try End Sub Index: CPersistentCollection.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentCollection.vb,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- CPersistentCollection.vb 21 Dec 2004 21:57:12 -0000 1.15 +++ CPersistentCollection.vb 14 Feb 2005 02:23:11 -0000 1.16 @@ -1,5 +1,7 @@ Option Explicit On Imports System.ComponentModel +Imports System.Reflection + '''----------------------------------------------------------------------------- ''' Project : AToMSFramework ''' Class : CPersistentCollection @@ -21,6 +23,7 @@ Inherits CollectionBase Implements IComponent Implements IBindingList + 'Implements ICloneable Private m_container As CPersistentObject @@ -41,7 +44,8 @@ ''' [rbanks] 17/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- - <Browsable(False)> Public Property ContainerObject() As CPersistentObject + <Browsable(False), Obsolete("Changes in collection management have made this obsolete. Please use the ListChanged event for equivalent functionality")> _ + Public Property ContainerObject() As CPersistentObject Get Return m_container End Get @@ -195,10 +199,10 @@ Private Sub ItemDirtiedHandler(ByVal sender As Object, ByVal e As EventArgs) ' Debug.WriteLine("Collection trapped item dirtied event for " & sender.GetType.Name) RaiseEvent ItemDirtied(Me, e) - If Not Me.ContainerObject Is Nothing Then - 'Debug.WriteLine("item dirtied - dirtying container") - ContainerObject.SetDirtyFlag() - End If + 'If Not Me.ContainerObject Is Nothing Then + ' 'Debug.WriteLine("item dirtied - dirtying container") + ' ContainerObject.SetDirtyFlag() + 'End If End Sub #End Region @@ -297,7 +301,6 @@ End Sub Protected Overrides Sub OnClearComplete() - ' Debug.WriteLine("CPColl clear complete") RaiseEvent ListChanged(Me, New ListChangedEventArgs(ListChangedType.Reset, 0)) End Sub @@ -342,4 +345,49 @@ RaiseEvent Disposed(Me, EventArgs.Empty) End Sub #End Region + + '#Region "ICloneable Interface" + ' Public Function Clone() As Object Implements System.ICloneable.Clone + ' Dim obj As CPersistentCollection + ' 'obj = Me.MemberwiseClone + ' 'Use reflection to copy all of the fields from Obj to me (by value) + ' Dim f, fields() As FieldInfo + ' Dim e, events() As EventInfo + ' Dim value As Object + ' Dim t As Type + ' Dim d, newD, delArray() As [Delegate] + ' Try + ' t = Me.GetType + ' obj = Activator.CreateInstance(t) + ' While Not t Is Nothing + ' fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + ' 'Note that this will copy event handlers as well + ' For Each f In fields + ' If f.FieldType.Name = f.Name & "Handler" Then + ' 'This is an event! + ' d = f.GetValue(Me) + ' If Not d Is Nothing Then + ' delArray = d.GetInvocationList + ' For Each d In delArray + ' If d.Target.Equals(obj) Then + ' newD = [Delegate].CreateDelegate(f.FieldType, obj, d.Target) + ' End If + ' Next + ' End If + ' End If + ' value = f.GetValue(Me) + ' f.SetValue(obj, value) + ' Next + ' If t.IsSubclassOf(GetType(CPersistentCollection)) Then + ' t = t.BaseType + ' Else + ' t = Nothing + ' End If + ' End While + ' Catch ex As Exception + ' Debug.WriteLine(ex.Message) + ' End Try + ' Return obj + ' End Function + '#End Region End Class Index: CPersistentObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentObject.vb,v retrieving revision 1.54 retrieving revision 1.55 diff -u -d -r1.54 -r1.55 --- CPersistentObject.vb 11 Feb 2005 02:51:37 -0000 1.54 +++ CPersistentObject.vb 14 Feb 2005 02:23:11 -0000 1.55 @@ -675,7 +675,7 @@ Return CallByName(o, propertyName, CallType.Get) End If Catch err As Exception - Throw New Exception("getCollectionByAttribute failed", err) + Throw New Exception("getCollectionByAttribute failed for class " & me.getclassmap.name & " attribute: " & " " & pname, err) End Try End Function @@ -1238,10 +1238,14 @@ '''----------------------------------------------------------------------------- Public Overridable Function Copy() As IPersistableObject Implements IPersistentObject.Copy Dim obj As CPersistentObject - obj = CType(Me.MemberwiseClone, CPersistentObject) + obj = Me.getClassMap.CreateObjectInstance + obj.ReplaceWith(Me) + '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 + 'This will also connect events from the collections to the new object based on + 'existing event handlers in "Me" + 'CPersistenceBroker.CopyCollections(Me, obj) Return obj End Function '''----------------------------------------------------------------------------- @@ -1258,22 +1262,26 @@ '''----------------------------------------------------------------------------- Public Overridable Sub ReplaceWith(ByVal obj As IPersistableObject) Implements IPersistentObject.ReplaceWith 'Use reflection to copy all of the fields from Obj to me (by value) + 'Also copy collections If obj Is Nothing Then Return If Not obj.GetObjectType Is Me.GetObjectType Then Throw New Exception("Objects must be of the same type") End If Dim f, fields() As FieldInfo Dim value As Object - Dim t As Type - Try + Dim t, iListType, iDicType As Type Try t = Me.GetType While Not t Is Nothing fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) 'Note that this will copy event handlers as well For Each f In fields - ' Debug.WriteLine(f.Name) - value = f.GetValue(obj) - f.SetValue(Me, value) + iListType = f.FieldType.GetInterface("IList", True) + iDicType = f.FieldType.GetInterface("IDictionary", True) + 'Do not copy collections yet - we'll do that at the end + If iListType Is Nothing AndAlso iDicType Is Nothing Then + value = f.GetValue(obj) + f.SetValue(Me, value) + End If Next If t.IsSubclassOf(GetType(CPersistentObject)) Then t = t.BaseType @@ -1281,7 +1289,7 @@ t = Nothing End If End While - Catch ex As Exception + CPersistenceBroker.CopyCollections(obj, Me) Catch ex As Exception Debug.WriteLine(ex.Message) End Try End Sub @@ -1675,37 +1683,37 @@ Return obj End Function - <EditorBrowsable(EditorBrowsableState.Advanced)> _ - Public Overridable Function GetBaseCopy() As CPersistentObject - 'Use reflection to copy all of the fields from Obj to me (by value) - If Me.getClassMap.SuperClass Is Nothing Then - Return Nothing - End If - Dim obj As CPersistentObject = Me.getClassMap.SuperClass.CreateObjectInstance - Dim f, fields() As FieldInfo - Dim value As Object - Dim t As Type - Try - t = obj.GetType - While Not t Is Nothing - fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) - 'Note that this will copy event handlers as well - For Each f In fields - value = f.GetValue(Me) - f.SetValue(obj, value) - Next - If t.IsSubclassOf(GetType(CPersistentObject)) Then - t = t.BaseType - Else - t = Nothing - End If - End While - Return obj - Catch ex As Exception - Debug.WriteLine(ex.Message) - End Try - Return Nothing - End Function + '<EditorBrowsable(EditorBrowsableState.Advanced)> _ + 'Public Overridable Function GetBaseCopy() As CPersistentObject + ' 'Use reflection to copy all of the fields from Obj to me (by value) + ' If Me.getClassMap.SuperClass Is Nothing Then + ' Return Nothing + ' End If + ' Dim obj As CPersistentObject = Me.getClassMap.SuperClass.CreateObjectInstance + ' Dim f, fields() As FieldInfo + ' Dim value As Object + ' Dim t As Type + ' Try + ' t = obj.GetType + ' While Not t Is Nothing + ' fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + ' 'Note that this will copy event handlers as well + ' For Each f In fields + ' value = f.GetValue(Me) + ' f.SetValue(obj, value) + ' Next + ' If t.IsSubclassOf(GetType(CPersistentObject)) Then + ' t = t.BaseType + ' Else + ' t = Nothing + ' End If + ' End While + ' Return obj + ' Catch ex As Exception + ' Debug.WriteLine(ex.Message) + ' End Try + ' Return Nothing + 'End Function #End Region |