Wednesday, January 11, 2006

 

CSLA.NET Switching root to child object and vice versa

I’ve managed to create my own switchable mechanism in CSLA .NET for editable object. I did tried to implement the original switchable editable object as presented by the author, but it confuses me a lot. As far as I understand to make the editable object switchable from root to child is by putting MarkAsChild() in the constructor of the object. When an editable child object is implemented calling Save() method it would throw an exception because it can’t be save directly. However, if we can manage to change the IsChild property from true to false then there will be no problem. But IsChild is a read only property.

So out of curiosity, I tried to use reflection to change the mIsChild of type boolean private variable to false to behave as a root object and setting it to true to behave as a child object and it works. So I decided to combine the implementation of child and root object rather than implementing switchable object.

When calling Save() method in:

So instead of duplicating the code from Update() to DataPortal_Update(), I simply call Update() in DataPortal_Update().

Below are codes for switching editable object from root to child and vice versa:

Public Sub ToRoot(ByVal o As Object)

Dim t As System.Type

t = o.GetType().BaseType()

If String.Compare(t.Name, "BusinessBase", True) > 0 Then
Throw New Exception("Not a CSLA object")
End If

Dim fi As FieldInfo = t.GetField("mIsChild", _
Reflection.BindingFlags.NonPublic Or BindingFlags.GetField Or BindingFlags.Instance _
Or BindingFlags.FlattenHierarchy Or BindingFlags.CreateInstance _
Or BindingFlags.SetField)

If fi Is Nothing Then
Throw New Exception("Unable to resolve CSLA object info")
End If

Dim IsChild As Boolean = fi.GetValue(o)

If Not IsChild Then
Throw New Exception("The object is already in Root")
End If

fi.SetValue(o, False)

End Sub

Public Sub ToChild(ByVal o As Object)

Dim t As System.Type

t = o.GetType().BaseType()

If String.Compare(t.Name, "BusinessBase", True) > 0 Then
Throw New Exception("Not a CSLA object")
End If

Dim fi As FieldInfo = t.GetField("mIsChild", _
Reflection.BindingFlags.NonPublic Or BindingFlags.GetField Or BindingFlags.Instance _
Or BindingFlags.FlattenHierarchy Or BindingFlags.CreateInstance _
Or BindingFlags.SetField)

If fi Is Nothing Then
Throw New Exception("Unable to resolve CSLA object info")
End If

Dim IsChild As Boolean = fi.GetValue(o)

If IsChild Then
Throw New Exception("The object is already in Child")
End If

fi.SetValue(o, True)

End Sub


Scenario: Switchng editable object (from child to root) inside a root collection

  1. Get a clone copy of the editable object from the root collection

    eobjName = DirectCast(Me.BindingContext(mNameCol.Current, eobjName).Clone()
  2. Call ToRoot()

    ToRoot(eobjName)
  3. Do necessary things to the root object you can also invoke Save() method

    'Do something with root object and save changes
    eobjName.Save()
  4. Call ToChild(), to reset the original setting

    ToChild(eobjName)
  5. Update root collection to update the content of it using the clone Object. Since there is no available method in BusinessBaseCollection to update the content of the collection you need to create a method UpdateCollection in the root collection

    Friend Sub UpdateCollection(ByVal o as eobjNameType)
    Dim i as Integer
    For i = 0 To List.Count - 1
    If DirectCast(List.Item(i), eobjNameType).Equals(o) Then
    List.Item(i) = o
    Exit For
    End If
    Next i
    End Sub

I know this is a hack version against the original implementation and I guess a lot of you guys will object on what I did. =)



Comments: Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?