Generic BusinessBase.Save() problem

Generic BusinessBase.Save() problem

Old forum URL: forums.lhotka.net/forums/t/444.aspx


Massong posted on Thursday, June 22, 2006

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

RockfordLhotka replied on Thursday, June 22, 2006

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.)

Massong replied on Thursday, June 22, 2006

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

Massong replied on Thursday, June 22, 2006

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?

RockfordLhotka replied on Thursday, June 22, 2006

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.

Massong replied on Friday, June 23, 2006

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

RockfordLhotka replied on Saturday, June 24, 2006

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.

ray replied on Monday, February 18, 2008

*bump*

Found this post and it completely complies with what I need to do.

So, I have something that works and want to make sure this would be the recommended save operation:
//To Apply Edit:
Csla.Core.BusinessBase bb = (Csla.Core.BusinessBase) myCslaObject;
bb.ApplyEdit();
//To Save:
Csla.Core.ISavable ISav = (Csla.Core.ISavable)bb;
ISav.Save();



RockfordLhotka replied on Tuesday, February 19, 2008

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