⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 businessbase.cs

📁 C# 版本的一个三层商业架构
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.ComponentModel;
using CSLA.Resources;

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# Business Objects' for
  /// full details on the use of this base class to create business
  /// objects.
  /// </para>
  /// </remarks>
  [Serializable()]
  abstract public class BusinessBase : Core.UndoableBase, 
    IEditableObject, ICloneable,
    IDataErrorInfo, Serialization.ISerializationNotification
  {
    #region IsNew, IsDeleted, IsDirty

    // keep track of whether we are new, deleted or dirty
    bool _isNew = true;
    bool _isDeleted = false;
    bool _isDirty = true;

    /// <summary>
    /// Returns True if this is a new object, False if it is a pre-existing object.
    /// </summary>
    /// <remarks>
    /// An object is considered to be new if its data doesn't correspond to
    /// data in the database. In other words, if the data values in this particular
    /// object have not yet been saved to the database the object is considered to
    /// be new. Likewise, if the object's data has been deleted from the database
    /// then the object is considered to be new.
    /// </remarks>
    /// <returns>A value indicating if this object is new.</returns>
    public bool IsNew
    {
      get
      {
        return _isNew;
      }
    }

    /// <summary>
    /// Returns True if this object is marked for deletion.
    /// </summary>
    /// <remarks>
    /// CSLA .NET supports both immediate and deferred deletion of objects. This
    /// property is part of the support for deferred deletion, where an object
    /// can be marked for deletion, but isn't actually deleted until the object
    /// is saved to the database. This property indicates whether or not the
    /// current object has been marked for deletion. If it is True, the object will
    /// be deleted when it is saved to the database, otherwise it will be inserted
    /// or updated by the save operation.
    /// </remarks>
    /// <returns>A value indicating if this object is marked for deletion.</returns>
    public bool IsDeleted
    {
      get
      {
        return _isDeleted;
      }
    }

    /// <summary>
    /// Returns True if this object's data has been changed.
    /// </summary>
    /// <remarks>
    /// <para>
    /// When an object's data is changed, CSLA .NET makes note of that change
    /// and considers the object to be 'dirty' or changed. This value is used to
    /// optimize data updates, since an unchanged object does not need to be
    /// updated into the database. All new objects are considered dirty. All objects
    /// marked for deletion are considered dirty.
    /// </para><para>
    /// Once an object's data has been saved to the database (inserted or updated)
    /// the dirty flag is cleared and the object is considered unchanged. Objects
    /// newly loaded from the database are also considered unchanged.
    /// </para>
    /// </remarks>
    /// <returns>A value indicating if this object's data has been changed.</returns>
    virtual public bool IsDirty
    {
      get
      {
        return _isDirty;
      }
    }

    /// <summary>
    /// Marks the object as being a new object. This also marks the object
    /// as being dirty and ensures that it is not marked for deletion.
    /// </summary>
    /// <remarks>
    /// <para>
    /// Newly created objects are marked new by default. You should call
    /// this method in the implementation of DataPortal_Update when the
    /// object is deleted (due to being marked for deletion) to indicate
    /// that the object no longer reflects data in the database.
    /// </para><para>
    /// If you override this method, make sure to call the base
    /// implementation after executing your new code.
    /// </para>
    /// </remarks>
    protected virtual void MarkNew()
    {
      _isNew = true;
      _isDeleted = false;
      MarkDirty();
    }

    /// <summary>
    /// Marks the object as being an old (not new) object. This also
    /// marks the object as being unchanged (not dirty).
    /// </summary>
    /// <remarks>
    /// <para>
    /// You should call this method in the implementation of
    /// DataPortal_Fetch to indicate that an existing object has been
    /// successfully retrieved from the database.
    /// </para><para>
    /// You should call this method in the implementation of 
    /// DataPortal_Update to indicate that a new object has been successfully
    /// inserted into the database.
    /// </para><para>
    /// If you override this method, make sure to call the base
    /// implementation after executing your new code.
    /// </para>
    /// </remarks>
    protected virtual void MarkOld()
    {
      _isNew = false;
      MarkClean();
    }

    /// <summary>
    /// Marks an object for deletion. This also marks the object
    /// as being dirty.
    /// </summary>
    /// <remarks>
    /// You should call this method in your business logic in the
    /// case that you want to have the object deleted when it is
    /// saved to the database.
    /// </remarks>
    protected void MarkDeleted()
    {
      _isDeleted = true;
      MarkDirty();
    }

    /// <summary>
    /// Marks an object as being dirty, or changed.
    /// </summary>
    /// <remarks>
    /// <para>
    /// You should call this method in your business logic any time
    /// the object's internal data changes. Any time any instance
    /// variable changes within the object, this method should be called
    /// to tell CSLA .NET that the object's data has been changed.
    /// </para><para>
    /// Marking an object as dirty does two things. First it ensures
    /// that CSLA .NET will properly save the object as appropriate. Second,
    /// it causes CSLA .NET to tell Windows Forms data binding that the
    /// object's data has changed so any bound controls will update to
    /// reflect the new values.
    /// </para>
    /// </remarks>
    protected void MarkDirty()
    {
      _isDirty = true;
      OnIsDirtyChanged();
    }

    private void MarkClean()
    {
      _isDirty = false;
      OnIsDirtyChanged();
    }

    #endregion

    #region IsSavable

    /// <summary>
    /// Returns True if this object is both dirty and valid.
    /// </summary>
    /// <remarks>
    /// An object is considered dirty (changed) if 
    /// <see cref="P:CSLA.BusinessBase.IsDirty" /> returns True. It is
    /// considered valid if <see cref="P:CSLA.BusinessBase.IsValid" /> 
    /// returns True. The IsSavable property is
    /// a combination of these two properties. It is provided specifically to
    /// enable easy binding to a Save or OK button on a form so that button
    /// can automatically enable/disable as the object's state changes between
    /// being savable and not savable. 
    /// </remarks>
    /// <returns>A value indicating if this object is new.</returns>
    public virtual bool IsSavable
    {
      get
      {
        return IsDirty && IsValid;
      }
    }

    #endregion

    #region IEditableObject

    [NotUndoable(), NonSerialized()]
    BusinessCollectionBase _parent;
    [NotUndoable()]
    bool _bindingEdit = false;
    bool _neverCommitted = true;

    /// <summary>
    /// Used by <see cref="T:CSLA.BusinessCollectionBase" /> as a
    /// child object is created to tell the child object about its
    /// parent.
    /// </summary>
    /// <param name="parent">A reference to the parent collection object.</param>
    internal void SetParent(BusinessCollectionBase parent)
    {
      if(!IsChild)
        throw new Exception(Strings.GetResourceString("ParentSetException"));
      _parent = parent;
    }

    /// <summary>
    /// Allow data binding to start a nested edit on the object.
    /// </summary>
    /// <remarks>
    /// Data binding may call this method many times. Only the first
    /// call should be honored, so we have extra code to detect this
    /// and do nothing for subsquent calls.
    /// </remarks>
    void IEditableObject.BeginEdit()
    {
      if(!_bindingEdit)
        BeginEdit();
    }

    /// <summary>
    /// Allow data binding to cancel the current edit.
    /// </summary>
    /// <remarks>
    /// Data binding may call this method many times. Only the first
    /// call to either IEditableObject.CancelEdit or 
    /// <see cref="M:CSLA.BusinessBase.IEditableObject_EndEdit">IEditableObject.EndEdit</see>
    /// should be honored. We include extra code to detect this and do
    /// nothing for subsequent calls.
    /// </remarks>
    void IEditableObject.CancelEdit()
    {
      if(_bindingEdit)
      {
        CancelEdit();
        if(IsNew && _neverCommitted && EditLevel <= EditLevelAdded)
        {
          // we're new and no EndEdit or ApplyEdit has ever been
          // called on us, and now we've been canceled back to 
          // where we were added so we should have ourselves  
          // removed from the parent collection
          if(!(_parent == null))
            _parent.RemoveChild(this);
        }
      }
    }

    /// <summary>
    /// Allow data binding to apply the current edit.
    /// </summary>
    /// <remarks>
    /// Data binding may call this method many times. Only the first
    /// call to either IEditableObject.EndEdit or 
    /// <see cref="M:CSLA.BusinessBase.IEditableObject_CancelEdit">
    /// IEditableObject.CancelEdit</see>
    /// should be honored. We include extra code to detect this and do
    /// nothing for subsequent calls.
    /// </remarks>
    void IEditableObject.EndEdit()
    {
      if(_bindingEdit)
        ApplyEdit();
    }

    #endregion

    #region Begin/Cancel/ApplyEdit

    /// <summary>
    /// Starts a nested edit on the object.
    /// </summary>
    /// <remarks>
    /// <para>
    /// When this method is called the object takes a snapshot of
    /// its current state (the values of its variables). This snapshot
    /// can be restored by calling <see cref="M:CSLA.BusinessBase.CancelEdit" />
    /// or committed by calling <see cref="M:CSLA.BusinessBase.ApplyEdit" />.
    /// </para><para>
    /// This is a nested operation. Each call to BeginEdit adds a new
    /// snapshot of the object's state to a stack. You should ensure that 
    /// for each call to BeginEdit there is a corresponding call to either 
    /// CancelEdit or ApplyEdit to remove that snapshot from the stack.
    /// </para><para>
    /// See Chapters 2 and 4 for details on n-level undo and state stacking.
    /// </para>
    /// </remarks>
    public void BeginEdit()
    {
      _bindingEdit = true;
      CopyState();
    }

    /// <summary>
    /// Cancels the current edit process, restoring the object's state to
    /// its previous values.
    /// </summary>
    /// <remarks>
    /// Calling this method causes the most recently taken snapshot of the 
    /// object's state to be restored. This resets the object's values
    /// to the point of the last <see cref="M:CSLA.BusinessBase.BeginEdit" />
    /// call.
    /// </remarks>
    public void CancelEdit()
    {
      _bindingEdit = false;
      UndoChanges();
      AddBusinessRules();
      OnIsDirtyChanged();
    }

    /// <summary>
    /// Commits the current edit process.
    /// </summary>
    /// <remarks>
    /// Calling this method causes the most recently taken snapshot of the 
    /// object's state to be discarded, thus committing any changes made
    /// to the object's state since the last <see cref="M:CSLA.BusinessBase.BeginEdit" />
    /// call.
    /// </remarks>
    public void ApplyEdit()
    {
      _bindingEdit = false;
      _neverCommitted = false;
      AcceptChanges();
    }

    #endregion

    #region IsChild

    [NotUndoable()]
    bool _isChild = false;

    protected internal bool IsChild
    {
      get
      {
        return _isChild;
      }
    }

    /// <summary>
    /// Marks the object as being a child object.
    /// </summary>
    /// <remarks>
    /// <para>
    /// By default all business objects are 'parent' objects. This means
    /// that they can be directly retrieved and updated into the database.
    /// </para><para>
    /// We often also need child objects. These are objects which are contained
    /// within other objects. For instance, a parent Invoice object will contain
    /// child LineItem objects.
    /// </para><para>
    /// To create a child object, the MarkAsChild method must be called as the
    /// object is created. Please see Chapter 7 for details on the use of the
    /// MarkAsChild method.
    /// </para>
    /// </remarks>
    protected void MarkAsChild()
    {
      _isChild = true;
    }

    #endregion

    #region Delete

    /// <summary>
    /// Marks the object for deletion. The object will be deleted as part of the
    /// next save operation.
    /// </summary>
    /// <remarks>
    /// <para>
    /// CSLA .NET supports both immediate and deferred deletion of objects. This
    /// method is part of the support for deferred deletion, where an object
    /// can be marked for deletion, but isn't actually deleted until the object
    /// is saved to the database. This method is called by the UI developer to
    /// mark the object for deletion.
    /// </para><para>
    /// To 'undelete' an object, use <see cref="M:CSLA.BusinessBase.BeginEdit" /> before
    /// calling the Delete method. You can then use <see cref="M:CSLA.BusinessBase.CancelEdit" />
    /// later to reset the object's state to its original values. This will include resetting
    /// the deleted flag to False.
    /// </para>
    /// </remarks>
    public void Delete()
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -