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