This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
I'm looking for a way to DeepClone objects in Lightspeed. Using a serialize and de-serialize does not work, as the ID's and state of the Entity etc cant be changed. If I could somehow use serialize,and then simply "reset" the status to "new" for that object and all sub-collections, so that if I saved the whole tree I'd get new records in the DB, and not updated ones. Is it possible / can it be done?
This would save me a LOT of work and effort, as our calculator used this method intensly. Anthony |
|
|
Hi Anthony, We don't provide this capability within LightSpeed itself. In applications where we have needed to undertake this ourselves we have added a method to each entity to copy it (which in turn calls to copy the children and thus they can walk the tree cloning the entities. That is the recommended approach to copying entities as it ensures a clean internal state. I hope that helps, John-Daniel |
|
|
Is there any specific reason why you don't recommand to clone entity using reflection? I have to clone a lot of entities of many types and creating a clone for each of them is very cumbersome. I have created my own clone engine. Can you tell me what could be wrong, not clean and can set my entity in a bad state using the sample below. Here is my tiny engine for cloning: *** Sorry for the french comments *** :)
''' <summary> ''' Permet d'effectuer des clones ''' </summary> Public Class EntityCloner ''' <summary> ''' Retourne un clone de l'entité. ''' </summary> Public Function Clone(Of T As Mindscape.LightSpeed.Entity)(ByVal entity As T) As T Return DirectCast(Me.CloneEntityInternal(entity), T) End Function
''' <summary> ''' Retourne un clone de l'entité. ''' </summary> Private Function CloneEntityInternal(ByVal entity As Object) As Object Dim newEntity As Object
newEntity = Activator.CreateInstance(entity.GetType())
Dim propertiesInfo() As System.Reflection.PropertyInfo = entity.GetType.GetProperties(System.Reflection.BindingFlags.Public Or Reflection.BindingFlags.GetProperty Or Reflection.BindingFlags.SetProperty Or Reflection.BindingFlags.Instance)
For Each propertyInfo As System.Reflection.PropertyInfo In propertiesInfo If Me.IsComposition(propertyInfo) Then Me.CloneCollection(entity, newEntity, propertyInfo) Else If Me.CanUpdateField(propertyInfo) Then Me.TransferData(entity, newEntity, propertyInfo) End If End If Next
Return newEntity End Function
''' <summary> ''' Transfert des données du champ de l'entité à cloner vers le champs de la ''' nouvelles entitée. ''' </summary> Private Sub TransferData(ByVal entity As Object, ByVal newEntity As Object, ByVal propertyInfo As System.Reflection.PropertyInfo) Dim value As Object
value = propertyInfo.GetValue(entity, Nothing, Nothing, Nothing, Nothing)
propertyInfo.SetValue(newEntity, value, Nothing, Nothing, Nothing, Nothing) End Sub
''' <summary> ''' Indique si le champ peut être modifié. ''' </summary> Private Function CanUpdateField(ByVal propertyInfo As System.Reflection.PropertyInfo) As Boolean If Me.CanTransferData(propertyInfo) Then If Not Me.IsAggregation(propertyInfo) Then If Not Me.IsEntityStateProperty(propertyInfo) Then Return True End If End If End If End Function
''' <summary> ''' Clone la liste des objets de la collection. ''' </summary> Private Sub CloneCollection(ByVal entity As Object, ByVal newEntity As Object, ByVal propertyInfo As System.Reflection.PropertyInfo) Dim entityCollection As IList Dim newCollection As IList
entityCollection = DirectCast(propertyInfo.GetValue(entity, Nothing, Nothing, Nothing, Nothing), IList)
If entityCollection.Count > 0 Then newCollection = DirectCast(propertyInfo.GetValue(newEntity, Nothing, Nothing, Nothing, Nothing), IList)
For i As Integer = 0 To entityCollection.Count - 1 Dim newSubEntity As Object
newSubEntity = Me.CloneEntityInternal(entityCollection.Item(i))
newCollection.Add(newSubEntity) Next End If End Sub
''' <summary> ''' Indique s'il est possible d'extraire les informations de la propriétés et de modifier ''' ces mêmes informations. ''' </summary> Private Function CanTransferData(ByVal propertyInfo As System.Reflection.PropertyInfo) As Boolean If Not propertyInfo.IsSpecialName Then If propertyInfo.CanWrite And propertyInfo.CanRead Then Return True End If End If End Function
''' <summary> ''' Indique si la propriété est une composition. ''' </summary> Private Function IsComposition(ByVal propertyInfo As System.Reflection.PropertyInfo) As Boolean If Not propertyInfo.IsSpecialName Then Return String.Compare(propertyInfo.PropertyType.Name, "EntityCollection`1", True) = 0 End If End Function
''' <summary> ''' Indique si c'est la propriété pour déterminer l'état de l'entité. ''' </summary> Private Function IsEntityStateProperty(ByVal propertyInfo As System.Reflection.PropertyInfo) As Boolean If propertyInfo.PropertyType Is GetType(Mindscape.LightSpeed.EntityState) Then Return True End If End Function
''' <summary> ''' Indique si la propriété est une aggrégation de l'objet; une propriété liée ''' par une clé étrangère à une autre table. ''' </summary> Private Function IsAggregation(ByVal propertyInfo As System.Reflection.PropertyInfo) As Boolean Return String.Compare(propertyInfo.PropertyType.BaseType.Name, "Entity`1", True) = 0 End Function End Class |
|
|
Hi, The only reason was that you're relying on us to not change some things. It's not a huge problem to be doing this so I wouldn't worry too much about it. We're working on adding some meta data improvements to LightSpeed 4 which may make this scenario easier and much tidier to code up so keep an eye on the blog for when we announce that. I forgive you for the French comments but I'm not so sure about the VB ;-) John-Daniel |
|