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 } }