254 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.ComponentModel;
 | |
| using Csla.Properties;
 | |
| 
 | |
| namespace Csla
 | |
| {
 | |
| 
 | |
|   /// <summary>
 | |
|   /// This is the base class from which most business objects
 | |
|   /// will be derived.
 | |
|   /// </summary>
 | |
|   /// <remarks>
 | |
|   /// <para>
 | |
|   /// This class is the core of the CSLA .NET framework. To create
 | |
|   /// a business object, inherit from this class.
 | |
|   /// </para><para>
 | |
|   /// Please refer to 'Expert C# 2005 Business Objects' for
 | |
|   /// full details on the use of this base class to create business
 | |
|   /// objects.
 | |
|   /// </para>
 | |
|   /// </remarks>
 | |
|   /// <typeparam name="T">Type of the business object being defined.</typeparam>
 | |
|   [Serializable()]
 | |
|   public abstract class BusinessBase<T> :
 | |
|     Core.BusinessBase, Core.ISavable where T : BusinessBase<T>
 | |
|   {
 | |
| 
 | |
|     #region Object ID Value
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Override this method to return a unique identifying
 | |
|     /// value for this object.
 | |
|     /// </summary>
 | |
|     /// <remarks>
 | |
|     /// 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 
 | |
|     /// <see langword="Nothing"/> and then manually override the
 | |
|     /// <see cref="Equals"/>, <see cref="GetHashCode"/> and
 | |
|     /// <see cref="ToString"/> methods in your business object.
 | |
|     /// </remarks>
 | |
|     protected abstract object GetIdValue();
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region System.Object Overrides
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Compares this object for equality with another object, using
 | |
|     /// the results of <see cref="GetIdValue"/> to determine
 | |
|     /// equality.
 | |
|     /// </summary>
 | |
|     /// <param name="obj">The object to be compared.</param>
 | |
|     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;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Returns a hash code value for this object, based on
 | |
|     /// the results of <see cref="GetIdValue"/>.
 | |
|     /// </summary>
 | |
|     public override int GetHashCode()
 | |
|     {
 | |
|       object id = GetIdValue();
 | |
|       if (id == null)
 | |
|         throw new ArgumentException(Resources.GetIdValueCantBeNull);
 | |
|       return id.GetHashCode();
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Returns a text representation of this object by
 | |
|     /// returning the <see cref="GetIdValue"/> value
 | |
|     /// in text form.
 | |
|     /// </summary>
 | |
|     public override string ToString()
 | |
|     {
 | |
|       object id = GetIdValue();
 | |
|       if (id == null)
 | |
|         throw new ArgumentException(Resources.GetIdValueCantBeNull);
 | |
|       return id.ToString();
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region Clone
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Creates a clone of the object.
 | |
|     /// </summary>
 | |
|     /// <returns>
 | |
|     /// A new object containing the exact data of the original object.
 | |
|     /// </returns>
 | |
|     public T Clone()
 | |
|     {
 | |
|       return (T)GetClone();
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region Data Access
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Saves the object to the database.
 | |
|     /// </summary>
 | |
|     /// <remarks>
 | |
|     /// <para>
 | |
|     /// 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.
 | |
|     /// </para><para>
 | |
|     /// If <see cref="Core.BusinessBase.IsDeleted" /> is <see langword="true"/>
 | |
|     /// the object will be deleted. Otherwise, if <see cref="Core.BusinessBase.IsNew" /> 
 | |
|     /// is <see langword="true"/> the object will be inserted. 
 | |
|     /// Otherwise the object's data will be updated in the database.
 | |
|     /// </para><para>
 | |
|     /// All this is contingent on <see cref="Core.BusinessBase.IsDirty" />. If
 | |
|     /// this value is <see langword="false"/>, no data operation occurs. 
 | |
|     /// It is also contingent on <see cref="Core.BusinessBase.IsValid" />. 
 | |
|     /// If this value is <see langword="false"/> an
 | |
|     /// exception will be thrown to indicate that the UI attempted to save an
 | |
|     /// invalid object.
 | |
|     /// </para><para>
 | |
|     /// 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.
 | |
|     /// </para><para>
 | |
|     /// 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 <c>base.Save()</c>.
 | |
|     /// </para>
 | |
|     /// </remarks>
 | |
|     /// <returns>A new object containing the saved values.</returns>
 | |
|     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;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Saves the object to the database, forcing
 | |
|     /// IsNew to <see langword="false"/> and IsDirty to True.
 | |
|     /// </summary>
 | |
|     /// <param name="forceUpdate">
 | |
|     /// If <see langword="true"/>, triggers overriding IsNew and IsDirty. 
 | |
|     /// If <see langword="false"/> then it is the same as calling Save().
 | |
|     /// </param>
 | |
|     /// <returns>A new object containing the saved values.</returns>
 | |
|     /// <remarks>
 | |
|     /// This overload is designed for use in web applications
 | |
|     /// when implementing the Update method in your 
 | |
|     /// data wrapper object.
 | |
|     /// </remarks>
 | |
|     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<Csla.Core.SavedEventArgs> _nonSerializableSavedHandlers;
 | |
|     [NotUndoable]
 | |
|     private EventHandler<Csla.Core.SavedEventArgs> _serializableSavedHandlers;
 | |
|     
 | |
|     /// <summary>
 | |
|     /// Event raised when an object has been saved.
 | |
|     /// </summary>
 | |
|     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
 | |
|       "CA1062:ValidateArgumentsOfPublicMethods")]
 | |
|     public event EventHandler<Csla.Core.SavedEventArgs> Saved
 | |
|     {
 | |
|       add
 | |
|       {
 | |
|         if (value.Method.IsPublic &&
 | |
|            (value.Method.DeclaringType.IsSerializable ||
 | |
|             value.Method.IsStatic))
 | |
|           _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
 | |
|             System.Delegate.Combine(_serializableSavedHandlers, value);
 | |
|         else
 | |
|           _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
 | |
|             System.Delegate.Combine(_nonSerializableSavedHandlers, value);
 | |
|       }
 | |
|       remove
 | |
|       {
 | |
|         if (value.Method.IsPublic &&
 | |
|            (value.Method.DeclaringType.IsSerializable ||
 | |
|             value.Method.IsStatic))
 | |
|           _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
 | |
|             System.Delegate.Remove(_serializableSavedHandlers, value);
 | |
|         else
 | |
|           _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
 | |
|             System.Delegate.Remove(_nonSerializableSavedHandlers, value);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Raises the Saved event, indicating that the
 | |
|     /// object has been saved, and providing a reference
 | |
|     /// to the new object instance.
 | |
|     /// </summary>
 | |
|     /// <param name="newObject">The new object instance.</param>
 | |
|     [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
 | |
|   }
 | |
| }
 |