sabato 6 ottobre 2007

Interfaccia IEditableObject, una implementazione generica

Ecco una classe che uso spesso come base dei miei Business Object, implementa l'interfaccia IEditableObject così da fornire la modifica dei dati transazionale a tutte le classi che la ereditano. L'interfaccia IEditableObject richiede di implementare i metodi BeginEdit, EndEdit e CancelEdit. Il metodo BeginEdit viene chiamato prima di iniziare la modifica dell'oggetto e si occupa di salvarne da qualche parte lo stato, il metodo CancelEdit serve per annullare l'operazione di modifica e ripristinare lo stato iniziale dell'oggetto, mentre il metodo EndEdit serve a confermare le modifiche eseguite sull'oggetto. E' da sottolineare il fatto che tra la chiamata a BeginEdit e la chiamata a uno tra EndEdit e CancelEdit possono intercorrere altre chiamate al metodo BeginEdit che devono essere ignorate. Come già detto il compito di BeginEdit è quello di salvare lo stato dell'oggetto così da poterlo poi ripristinare nel caso in cui l'utente volesse annullare le modifiche. A tale scopo sfrutteremo una Collection e la potenza della classe Reflection. Vediamo come: facendo uso della Reflection scoveremo tutte le proprietà pubbliche dell'oggetto e, scorrendole una dopo l'altra, salveremo il valore di ognuna di esse in una Collection usando come chiave il nome della proprietà. All'inizio del metodo BeginEdit metteremo un controllo sul valore della Collection, se questa non è nothing vuol dire che non si tratta della prima chiamata a BeginEdit e quindi usciamo dalla procedura, viceversa se la Collection è nothing allora possiamo istanziarla e procedere con il salvataggio dello stato. Il metodo EndEdit si occupa della conferma dei dati, ci limiteremo quindi a settare la Collection a nothing per far si che una successiva chiamata a BeginEdit non venga ignorata. Nel metodo CancelEdit vengono compiute le operazione inverse di quelle che si eseguono nel metodo BeginEdit, si leggono cioè i valori salvati nella Collection e si settano le proprietà dell'oggetto.



Public Class bcc_EditableObject
Implements System.ComponentModel.IEditableObject

Private mTmpData As Collection

Public Sub BeginEdit() _
Implements System.ComponentModel.IEditableObject.BeginEdit

' solo la prima BeginEdit ha effetto
If Not IsNothing(mTmpData) Then Exit Sub

Dim pi_src As Reflection.PropertyInfo

mTmpData = New Collection

For Each pi_src In _
Me.GetType.GetProperties( _
Reflection.BindingFlags.Public Or _
Reflection.BindingFlags.Instance)

' la proprietà non deve essere ReadOnly
If pi_src.CanWrite Then

mTmpData.Add(pi_src.GetValue(Me, Nothing), pi_src.Name)

End If

Next

End Sub


Public Sub CancelEdit() _
Implements System.ComponentModel.IEditableObject.CancelEdit

' nulla da ripristinare
If IsNothing(mTmpData) Then Exit Sub

Dim pi_src As Reflection.PropertyInfo

For Each pi_src In _
Me.GetType.GetProperties( _
Reflection.BindingFlags.Public Or _
Reflection.BindingFlags.Instance)

' la proprietà non deve essere ReadOnly
If pi_src.CanWrite Then

pi_src.SetValue(Me, mTmpData.Item(pi_src.Name), Nothing)

End If

Next

End Sub


Public Sub EndEdit() _
Implements System.ComponentModel.IEditableObject.EndEdit

' via libera alla prossima BeginEdit
mTmpData = Nothing

End Sub

End Class


Nessun commento: