using System;
using System.ComponentModel;
using Csla.Properties;
namespace Csla
{
///
/// This is the base class from which most business objects
/// will be derived.
///
///
///
/// This class is the core of the CSLA .NET framework. To create
/// a business object, inherit from this class.
///
/// Please refer to 'Expert C# 2005 Business Objects' for
/// full details on the use of this base class to create business
/// objects.
///
///
/// Type of the business object being defined.
[Serializable()]
public abstract class BusinessBase :
Core.BusinessBase, Core.ISavable where T : BusinessBase
{
#region Object ID Value
///
/// Override this method to return a unique identifying
/// value for this object.
///
///
/// If you can not provide a unique identifying value, it
/// is best if you can generate such a unique value (even
/// temporarily). If you can not do that, then return
/// and then manually override the
/// , and
/// methods in your business object.
///
protected abstract object GetIdValue();
#endregion
#region System.Object Overrides
///
/// Compares this object for equality with another object, using
/// the results of to determine
/// equality.
///
/// The object to be compared.
public override bool Equals(object obj)
{
if (obj is T)
{
object id = GetIdValue();
if (id == null)
throw new ArgumentException(Resources.GetIdValueCantBeNull);
return id.Equals(((T)obj).GetIdValue());
}
else
return false;
}
///
/// Returns a hash code value for this object, based on
/// the results of .
///
public override int GetHashCode()
{
object id = GetIdValue();
if (id == null)
throw new ArgumentException(Resources.GetIdValueCantBeNull);
return id.GetHashCode();
}
///
/// Returns a text representation of this object by
/// returning the value
/// in text form.
///
public override string ToString()
{
object id = GetIdValue();
if (id == null)
throw new ArgumentException(Resources.GetIdValueCantBeNull);
return id.ToString();
}
#endregion
#region Clone
///
/// Creates a clone of the object.
///
///
/// A new object containing the exact data of the original object.
///
public T Clone()
{
return (T)GetClone();
}
#endregion
#region Data Access
///
/// Saves the object to the database.
///
///
///
/// Calling this method starts the save operation, causing the object
/// to be inserted, updated or deleted within the database based on the
/// object's current state.
///
/// If is
/// the object will be deleted. Otherwise, if
/// is the object will be inserted.
/// Otherwise the object's data will be updated in the database.
///
/// All this is contingent on . If
/// this value is , no data operation occurs.
/// It is also contingent on .
/// If this value is an
/// exception will be thrown to indicate that the UI attempted to save an
/// invalid object.
///
/// It is important to note that this method returns a new version of the
/// business object that contains any data updated during the save operation.
/// You MUST update all object references to use this new version of the
/// business object in order to have access to the correct object data.
///
/// You can override this method to add your own custom behaviors to the save
/// operation. For instance, you may add some security checks to make sure
/// the user can save the object. If all security checks pass, you would then
/// invoke the base Save method via base.Save().
///
///
/// A new object containing the saved values.
public virtual T Save()
{
T result;
if (this.IsChild)
throw new NotSupportedException(Resources.NoSaveChildException);
if (EditLevel > 0)
throw new Validation.ValidationException(Resources.NoSaveEditingException);
if (!IsValid)
throw new Validation.ValidationException(Resources.NoSaveInvalidException);
if (IsDirty)
result = (T)DataPortal.Update(this);
else
result = (T)this;
OnSaved(result);
return result;
}
///
/// Saves the object to the database, forcing
/// IsNew to and IsDirty to True.
///
///
/// If , triggers overriding IsNew and IsDirty.
/// If then it is the same as calling Save().
///
/// A new object containing the saved values.
///
/// This overload is designed for use in web applications
/// when implementing the Update method in your
/// data wrapper object.
///
public T Save(bool forceUpdate)
{
if (forceUpdate && IsNew)
{
// mark the object as old - which makes it
// not dirty
MarkOld();
// now mark the object as dirty so it can save
MarkDirty(true);
}
return this.Save();
}
#endregion
#region ISavable Members
object Csla.Core.ISavable.Save()
{
return Save();
}
[NonSerialized]
[NotUndoable]
private EventHandler _nonSerializableSavedHandlers;
[NotUndoable]
private EventHandler _serializableSavedHandlers;
///
/// Event raised when an object has been saved.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1062:ValidateArgumentsOfPublicMethods")]
public event EventHandler Saved
{
add
{
if (value.Method.IsPublic &&
(value.Method.DeclaringType.IsSerializable ||
value.Method.IsStatic))
_serializableSavedHandlers = (EventHandler)
System.Delegate.Combine(_serializableSavedHandlers, value);
else
_nonSerializableSavedHandlers = (EventHandler)
System.Delegate.Combine(_nonSerializableSavedHandlers, value);
}
remove
{
if (value.Method.IsPublic &&
(value.Method.DeclaringType.IsSerializable ||
value.Method.IsStatic))
_serializableSavedHandlers = (EventHandler)
System.Delegate.Remove(_serializableSavedHandlers, value);
else
_nonSerializableSavedHandlers = (EventHandler)
System.Delegate.Remove(_nonSerializableSavedHandlers, value);
}
}
///
/// Raises the Saved event, indicating that the
/// object has been saved, and providing a reference
/// to the new object instance.
///
/// The new object instance.
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void OnSaved(T newObject)
{
Csla.Core.SavedEventArgs args = new Csla.Core.SavedEventArgs(newObject);
if (_nonSerializableSavedHandlers != null)
_nonSerializableSavedHandlers.Invoke(this, args);
if (_serializableSavedHandlers != null)
_serializableSavedHandlers.Invoke(this, args);
}
#endregion
}
}