Business Logic Toolkit for .NET
www.bltoolkit.net
|  Home   |  Download   |  Documentation   |  Discussions   |  License   |

  Source.EditableObjects.EditableObject.cs

 
using System;
using System.Collections;
using System.ComponentModel;
using System.Data.SqlTypes;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Xml;
using System.Xml.Serialization;

using BLToolkit.Common;
using BLToolkit.ComponentModel;
using BLToolkit.Mapping;
using BLToolkit.Reflection;
using BLToolkit.TypeBuilder;
using BLToolkit.Validation;

namespace BLToolkit.EditableObjects
{
    #region Instance Types
    [GlobalInstanceType(typeof(byte),     typeof(EditableValue<byte>))]
    [GlobalInstanceType(typeof(char),     typeof(EditableValue<char>))]
    [GlobalInstanceType(typeof(ushort),   typeof(EditableValue<ushort>))]
    [GlobalInstanceType(typeof(uint),     typeof(EditableValue<uint>))]
    [GlobalInstanceType(typeof(ulong),    typeof(EditableValue<ulong>))]
    [GlobalInstanceType(typeof(bool),     typeof(EditableValue<bool>))]
    [GlobalInstanceType(typeof(sbyte),    typeof(EditableValue<sbyte>))]
    [GlobalInstanceType(typeof(short),    typeof(EditableValue<short>))]
    [GlobalInstanceType(typeof(int),      typeof(EditableValue<int>))]
    [GlobalInstanceType(typeof(long),     typeof(EditableValue<long>))]
    [GlobalInstanceType(typeof(float),    typeof(EditableValue<float>))]
    [GlobalInstanceType(typeof(double),   typeof(EditableValue<double>))]
    [GlobalInstanceType(typeof(string),   typeof(EditableValue<string>), "")]
    [GlobalInstanceType(typeof(DateTime), typeof(EditableValue<DateTime>))]
    [GlobalInstanceType(typeof(decimal),  typeof(EditableValue<decimal>))]
    [GlobalInstanceType(typeof(Guid),     typeof(EditableValue<Guid>))]

    [GlobalInstanceType(typeof(byte?),     typeof(EditableValue<byte?>))]
    [GlobalInstanceType(typeof(char?),     typeof(EditableValue<char?>))]
    [GlobalInstanceType(typeof(ushort?),   typeof(EditableValue<ushort?>))]
    [GlobalInstanceType(typeof(uint?),     typeof(EditableValue<uint?>))]
    [GlobalInstanceType(typeof(ulong?),    typeof(EditableValue<ulong?>))]
    [GlobalInstanceType(typeof(bool?),     typeof(EditableValue<bool?>))]
    [GlobalInstanceType(typeof(sbyte?),    typeof(EditableValue<sbyte?>))]
    [GlobalInstanceType(typeof(short?),    typeof(EditableValue<short?>))]
    [GlobalInstanceType(typeof(int?),      typeof(EditableValue<int?>))]
    [GlobalInstanceType(typeof(long?),     typeof(EditableValue<long?>))]
    [GlobalInstanceType(typeof(float?),    typeof(EditableValue<float?>))]
    [GlobalInstanceType(typeof(double?),   typeof(EditableValue<double?>))]
    [GlobalInstanceType(typeof(DateTime?), typeof(EditableValue<DateTime?>))]
    [GlobalInstanceType(typeof(decimal?),  typeof(EditableValue<decimal?>))]
    [GlobalInstanceType(typeof(Guid?),     typeof(EditableValue<Guid?>))]

    [GlobalInstanceType(typeof(SqlBoolean),  typeof(EditableValue<SqlBoolean>))]
    [GlobalInstanceType(typeof(SqlByte),     typeof(EditableValue<SqlByte>))]
    [GlobalInstanceType(typeof(SqlDateTime), typeof(EditableValue<SqlDateTime>))]
    [GlobalInstanceType(typeof(SqlDecimal),  typeof(EditableValue<SqlDecimal>))]
    [GlobalInstanceType(typeof(SqlDouble),   typeof(EditableValue<SqlDouble>))]
    [GlobalInstanceType(typeof(SqlGuid),     typeof(EditableValue<SqlGuid>))]
    [GlobalInstanceType(typeof(SqlInt16),    typeof(EditableValue<SqlInt16>))]
    [GlobalInstanceType(typeof(SqlInt32),    typeof(EditableValue<SqlInt32>))]
    [GlobalInstanceType(typeof(SqlInt64),    typeof(EditableValue<SqlInt64>))]
    [GlobalInstanceType(typeof(SqlMoney),    typeof(EditableValue<SqlMoney>))]
    [GlobalInstanceType(typeof(SqlSingle),   typeof(EditableValue<SqlSingle>))]
    [GlobalInstanceType(typeof(SqlString),   typeof(EditableValue<SqlString>), "")]

    [GlobalInstanceType(typeof(XmlDocument),    typeof(EditableXmlDocument))]
    [GlobalInstanceType(typeof(EditableObject), typeof(EditableObjectHolder), IsObjectHolder=true)]
    #endregion
    [ImplementInterface(typeof(IEditable))]
    [ImplementInterface(typeof(IMemberwiseEditable))]
    [ImplementInterface(typeof(IPrintDebugState))]
    [ImplementInterface(typeof(ISetParent))]
    [ComVisible(true)]
    [Serializable]
    public abstract class EditableObject : EntityBase,
        ICloneable, IEditableObject, INotifyPropertyChanged,
        ISupportMapping, IValidatable, IPropertyChanged, INotifyObjectEdit
    {
        #region Constructor

        protected EditableObject()
        {
            ISetParent setParent = this as ISetParent;

            if (setParent != null)
                setParent.SetParent(this, null);
        }

        #endregion

        #region IEditable

        public virtual void AcceptChanges()
        {
            if (this is IEditable)
                ((IEditable)this).AcceptChanges();
        }

        public virtual void RejectChanges()
        {
            PropertyInfo[] dirtyMembers = GetDirtyMembers();

            if (this is IEditable)
                ((IEditable)this).RejectChanges();

            foreach (PropertyInfo dirtyMember in dirtyMembers)
                OnPropertyChanged(dirtyMember.Name);
        }

        [MapIgnore, Bindable(false)]
        public virtual bool IsDirty
        {
            get { return this is IEditable? ((IEditable)this).IsDirty: false; }
        }

        public virtual void AcceptMemberChanges(string memberName)
        {
            if (this is IMemberwiseEditable)
                ((IMemberwiseEditable)this).AcceptMemberChanges(null, memberName);
        }

        public virtual void RejectMemberChanges(string memberName)
        {
            bool notifyChange = IsDirtyMember(memberName);

            if (this is IMemberwiseEditable)
                ((IMemberwiseEditable)this).RejectMemberChanges(null, memberName);

            if (notifyChange)
                OnPropertyChanged(memberName);
        }

        public virtual bool IsDirtyMember(string memberName)
        {
            bool isDirty = false;

            if (this is IMemberwiseEditable)
                ((IMemberwiseEditable)this).IsDirtyMember(null, memberName, ref isDirty);

            return isDirty;
        }

        public virtual PropertyInfo[] GetDirtyMembers()
        {
            ArrayList list = new ArrayList();

            if (this is IMemberwiseEditable)
                ((IMemberwiseEditable)this).GetDirtyMembers(null, list);

            return (PropertyInfo[])list.ToArray(typeof(PropertyInfo));
        }

        [MapIgnore, Bindable(false)]
        public virtual string PrintDebugState
        {
            get
            {
#if DEBUG
                if (this is IPrintDebugState)
                {
                    string s = string.Format(
                        "====== {0} ======\r\nIsDirty: {1}\r\n" +
                        "Property       IsDirty Original                                 Current\r\n" +
                        "==================== = ======================================== ========================================\r\n",
                        GetType().Name, IsDirty);

                    ((IPrintDebugState)this).PrintDebugState(null, ref s);

                    return s + "\r\n";
                }
#endif
                return "";
            }
        }

        #endregion

        #region ISupportMapping Members

        private bool _isInMapping;
        [MapIgnore, Bindable(false)]
        public  bool  IsInMapping
        {
            get { return _isInMapping; }
        }

        protected void SetIsInMapping(bool isInMapping)
        {
            _isInMapping = isInMapping;
        }

        public virtual void BeginMapping(InitContext initContext)
        {
            _isInMapping = true;
        }

        public virtual void EndMapping(InitContext initContext)
        {
            if (initContext.IsDestination)
                AcceptChanges();

            _isInMapping = false;

            if (initContext.IsDestination)
                OnPropertyChanged("");
        }

        #endregion

        #region Notify Changes

        protected internal virtual void OnPropertyChanged(string propertyName)
        {
            if (NotifyChanges && PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private int _notNotifyChangesCount = 0;
        [MapIgnore, Bindable(false), XmlIgnore]
        public  bool  NotifyChanges
        {
            get { return _notNotifyChangesCount == 0;   }
            set { _notNotifyChangesCount = value? 0: 1; }
        }

        public void LockNotifyChanges()
        {
            _notNotifyChangesCount++;
        }

        public void UnlockNotifyChanges()
        {
            _notNotifyChangesCount--;

            if (_notNotifyChangesCount < 0)
                throw new InvalidOperationException();
        }

        #endregion

        #region IPropertyChanged Members

        void IPropertyChanged.OnPropertyChanged(PropertyInfo propertyInfo)
        {
            if (_isInMapping == false)
                OnPropertyChanged(propertyInfo.Name);
        }

        #endregion

        #region INotifyPropertyChanged Members

        [field : NonSerialized]
        public virtual event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IEditableObject Members

        public virtual void BeginEdit()
        {
            if (ObjectEdit != null)
                ObjectEdit(this, new ObjectEditEventArgs(ObjectEditType.Begin));
        }

        public virtual void CancelEdit()
        {
            if (ObjectEdit != null)
                ObjectEdit(this, new ObjectEditEventArgs(ObjectEditType.Cancel));
        }

        public virtual void EndEdit()
        {
            if (ObjectEdit != null)
                ObjectEdit(this, new ObjectEditEventArgs(ObjectEditType.End));
        }

        #endregion

        #region INotifyObjectEdit Members

        public event ObjectEditEventHandler ObjectEdit;

        #endregion

        #region ICloneable Members

        ///<summary>
        ///Creates a new object that is a copy of the current instance.
        ///</summary>
        ///<returns>
        ///A new object that is a copy of this instance.
        ///</returns>
        object ICloneable.Clone()
        {
            return TypeAccessor.Copy(this);
        }

        #endregion
    }
}
 
© 2010 www.bltoolkit.net
support@bltoolkit.net