Hi all,
I have written a BackgroundSaver component for my CSLA 1.x project that accepts any kind of Business Object, puts it into a FIFO, and saves it in a background thread by just calling its .Save() method. Now I try to upgrade this component to CSLA 2.0.2 and have a problem with the generic type of BusinessBase...
My old code looks like this:
While mList.Count > 0
Dim obj As BusinessBase = Nothing
Try
obj = CType(mList(0), BusinessBase)
obj = obj.Save
Catch ex As Exception
' (Error handling)
Finally
mList.RemoveAt(0)
End Try
End While
How can I write this in CSLA 2.x? My problem is that I can’t cast the list entries to Csla.BuisnessBase because the compiler wants to see a (of T) and I don’t know the exact type. Also I can’t cast them to Core.BuisenessBase because Core.BusinessBase doesn’t implement the Save-method...
Must I really use reflection to solve this problem?
Thanks,
Christian
You don't need to use reflection, no.
What you can do is define an ISavable interface:
Public Interface ISavable
Function Save() As Object
End Interface
And have all your business objects implement this interface. Of course a better approach is to create custom base classes of your own to abstract BusinessBase<T> and BusinessListBase<T>, which implement this interface. Kind of like this:
<Serializable()> _
Public Class MyBase(Of T As MyBase(Of T))
Inherits Csla.BusinessBase(Of T)
Implements ISavable
Private Function ISavable_Save() As Object Implements ISavable.Save
Return Me.Save()
End Function
End Class
You lose the strong typing of the normal Save(), but you gain the ability to write the component you are after.
I am considering adding this concept directly into version 2.1, because it is a common request and there's no harm in adding this idea (it doesn't break existing code, etc.)
Hi Rocky,
thanks for your fast reply.
I have just upgraded nearly all of my hundreds of classes to CSLA 2.x and I inherit them from BuisenessBase(Of T). I’m a little bit horrified by editing all this classes again. At the moment I use this BackgroundSaver only to save orders and tours. So maybe I should create an OrderBackgroundSaver and a TourBackgroundSaver component instead...
Greetings,
Christian
Hi Rocky,
couldn’t you move the save-method to Core.BusinessBase like this
Class Core.BusinessBase
Public Overridable Function SaveItem() As Core.BusinessBase
…
End Function
End Class
and call it in the Csla.BuisnessBase like this
Class BusinessBase(Of T As BusinessBase(Of T))
Public Overridable Function Save() As T
Return CType(Me.SaveItem, T)
End Function
End Class
so that it is possible to call SaveItem without strong typing or Save with strong typing as necessary?
Yes, but remember that BusinessListBase can also be a root object. In the general case, you need to be able to save both BusinessBase-derived and BusinessListBase-derived editable root objects.
While you might not have that case, it is at least something I need to consider to incorporate this idea into the framework itself.
I see – that wouldn’t work because of BusinessListBase inherits directly from System.ComponentModel.BindingList. I thought it would work the same way. There would be a Core.BusinessListBase necessary...
Greetings,
Christian
I think a few posts were lost due to the system crash and subsequent restore of the backup.
I'd replied here that I am putting ISavable into version 2.1, so both BusinessBase<T> and BusinessListBase<T> will implement this interface and you can use its loosely typed Save() method.
This enables other base form class and UI framework scenarios, as well as allowing me to write a new EditableRootListBase class for 2.1.
It is probably better to use interfaces throughout:
// unbind object from UI
((Csla.Core.ISupportUndo)myObject).ApplyEdit();
object result = ((Csla.Core.ISavable)myObject).Save();
// rebind UI to ‘result’
Rocky
Copyright (c) Marimer LLC