File: AuthoringOM\DependencyProperty.cs
Project: ndp\cdf\src\WF\Common\System.Workflow.ComponentModel.csproj (System.Workflow.ComponentModel)
#region Using directives
 
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
using System.Workflow.ComponentModel.Compiler;
using System.Runtime.CompilerServices;
using System.Security.Permissions;
 
#endregion
 
namespace System.Workflow.ComponentModel
{
    //
 
    [Serializable]
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class DependencyProperty : ISerializable
    {
        private static IDictionary<int, DependencyProperty> dependencyProperties = new Dictionary<int, DependencyProperty>();
 
        internal enum PropertyValidity
        {
            Uninitialize,
            Reexecute,
            Always
        }
 
        class KnownDependencyProperty
        {
            internal DependencyProperty dependencyProperty;
            //indicates whether this property, survives beyond Uninitialize.
            internal PropertyValidity propertyValidity;
 
            internal KnownDependencyProperty(DependencyProperty dependencyProperty, PropertyValidity propertyValidity)
            {
                this.dependencyProperty = dependencyProperty;
                this.propertyValidity = propertyValidity;
            }
        }
 
        private static KnownDependencyProperty[] knownProperties = new KnownDependencyProperty[256];
        
        private bool isRegistered = false;
        private string name = String.Empty;
        private System.Type propertyType = null;
        private System.Type ownerType = null;
        private System.Type validatorType = null;
        private PropertyMetadata defaultMetadata = null;
        private byte knownIndex = (byte)0;
        [NonSerialized]
        private bool isEvent = false;
 
        public static DependencyProperty Register(string name, System.Type propertyType, System.Type ownerType)
        {
            return ValidateAndRegister(name, propertyType, ownerType, null, null, true);
        }
 
        public static DependencyProperty Register(string name, System.Type propertyType, System.Type ownerType, PropertyMetadata defaultMetadata)
        {
            return ValidateAndRegister(name, propertyType, ownerType, defaultMetadata, null, true);
        }
 
        public static DependencyProperty RegisterAttached(string name, System.Type propertyType, System.Type ownerType)
        {
            return ValidateAndRegister(name, propertyType, ownerType, null, null, false);
        }
 
        public static DependencyProperty RegisterAttached(string name, System.Type propertyType, System.Type ownerType, PropertyMetadata defaultMetadata)
        {
            return ValidateAndRegister(name, propertyType, ownerType, defaultMetadata, null, false);
        }
        
        internal static void RegisterAsKnown(DependencyProperty dependencyProperty, byte byteVal, PropertyValidity propertyValidity)
        {
            if (dependencyProperty == null)
                throw new ArgumentNullException("dependencyProperty");
            if (knownProperties[byteVal] != null)
            {
                throw new InvalidOperationException(SR.GetString(SR.Error_AlreadyRegisteredAs, knownProperties[byteVal].dependencyProperty.ToString()));
            }
 
            dependencyProperty.KnownIndex = byteVal;
            knownProperties[byteVal] = new KnownDependencyProperty(dependencyProperty, propertyValidity);
        }
 
        internal static DependencyProperty FromKnown(Byte byteVal)
        {
            if (knownProperties[byteVal] == null)
            {
                throw new InvalidOperationException(SR.GetString(SR.Error_NotRegisteredAs, knownProperties[byteVal].dependencyProperty.ToString()));
            }
 
            return knownProperties[byteVal].dependencyProperty;
        }
 
        //TBD: Dharma - Get rid of this overload
        public static DependencyProperty RegisterAttached(string name, System.Type propertyType, System.Type ownerType, PropertyMetadata defaultMetadata, System.Type validatorType)
        {
            if (validatorType == null)
                throw new ArgumentNullException("validatorType");
            else if (!typeof(Validator).IsAssignableFrom(validatorType))
                throw new ArgumentException(SR.GetString(SR.Error_ValidatorTypeIsInvalid), "validatorType");
 
            return ValidateAndRegister(name, propertyType, ownerType, defaultMetadata, validatorType, false);
        }
 
        public static DependencyProperty FromName(string propertyName, Type ownerType)
        {
            if (propertyName == null)
                throw new ArgumentNullException("propertyName");
 
            if (ownerType == null)
                throw new ArgumentNullException("ownerType");
 
            DependencyProperty dp = null;
            while ((dp == null) && (ownerType != null))
            {
                // Ensure static constructor of type has run
                RuntimeHelpers.RunClassConstructor(ownerType.TypeHandle);
 
                // Locate property
                int hashCode = propertyName.GetHashCode() ^ ownerType.GetHashCode();
                lock (((ICollection)DependencyProperty.dependencyProperties).SyncRoot)
                {
                    if (DependencyProperty.dependencyProperties.ContainsKey(hashCode))
                        dp = DependencyProperty.dependencyProperties[hashCode];
                }
 
                ownerType = ownerType.BaseType;
            }
 
            return dp;
        }
 
        public static IList<DependencyProperty> FromType(Type ownerType)
        {
            if (ownerType == null)
                throw new ArgumentNullException("ownerType");
 
            // Ensure static constructor of type has run
            RuntimeHelpers.RunClassConstructor(ownerType.TypeHandle);
 
            List<DependencyProperty> filteredProperties = new List<DependencyProperty>();
            lock (((ICollection)DependencyProperty.dependencyProperties).SyncRoot)
            {
                foreach (DependencyProperty dependencyProperty in DependencyProperty.dependencyProperties.Values)
                {
                    if (TypeProvider.IsSubclassOf(ownerType, dependencyProperty.ownerType)
                        || ownerType == dependencyProperty.ownerType)
                        filteredProperties.Add(dependencyProperty);
                }
            }
 
            return filteredProperties.AsReadOnly();
        }
 
        private static DependencyProperty ValidateAndRegister(string name, System.Type propertyType, System.Type ownerType, PropertyMetadata defaultMetadata, System.Type validatorType, bool isRegistered)
        {
            if (name == null)
                throw new ArgumentNullException("name");
 
            if (name.Length == 0)
                throw new ArgumentException(SR.GetString(SR.Error_EmptyArgument), "name");
 
            if (propertyType == null)
                throw new ArgumentNullException("propertyType");
 
            if (ownerType == null)
                throw new ArgumentNullException("ownerType");
 
            FieldInfo fieldInfo = null;
            bool isEvent = (typeof(System.Delegate).IsAssignableFrom(propertyType) && (defaultMetadata == null || (defaultMetadata.Options & DependencyPropertyOptions.DelegateProperty) == 0));
 
            // WinOE Bug 13807: events can not be meta properties.
            if (isEvent && defaultMetadata != null && defaultMetadata.IsMetaProperty)
                throw new ArgumentException(SR.GetString(SR.Error_DPAddHandlerMetaProperty), "defaultMetadata");
 
            //Field must exists
            if (isEvent)
                fieldInfo = ownerType.GetField(name + "Event", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.GetProperty);
            else
                fieldInfo = ownerType.GetField(name + "Property", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.GetProperty);
 
            if (fieldInfo == null)
            {
                string error = SR.GetString((isEvent) ? SR.Error_DynamicEventNotSupported : SR.Error_DynamicPropertyNotSupported, new object[] { ownerType.FullName, name });
                throw new ArgumentException(error, "ownerType");
            }
 
 
            PropertyMetadata metadata = null;
            object defaultValue = null;
 
            // Establish default metadata for all types, if none is provided
            if (defaultMetadata == null)
            {
                defaultValue = GetDefaultValue(name, propertyType, ownerType);
                metadata = new PropertyMetadata(defaultValue);
            }
            else
            {
                metadata = defaultMetadata;
                if (metadata.DefaultValue == null)
                    metadata.DefaultValue = GetDefaultValue(name, propertyType, ownerType);
            }
 
            DependencyProperty dependencyProperty = new DependencyProperty(name, propertyType, ownerType, metadata, validatorType, isRegistered);
            lock (((ICollection)DependencyProperty.dependencyProperties).SyncRoot)
            {
                if (DependencyProperty.dependencyProperties.ContainsKey(dependencyProperty.GetHashCode()))
                    throw new InvalidOperationException(SR.GetString(SR.Error_DPAlreadyExist, new object[] { name, ownerType.FullName }));
 
                DependencyProperty.dependencyProperties.Add(dependencyProperty.GetHashCode(), dependencyProperty);
            }
 
            return dependencyProperty;
        }
 
        private static object GetDefaultValue(string name, System.Type propertyType, System.Type ownerType)
        {
            if (name == null)
                throw new ArgumentNullException("name");
 
            if (name.Length == 0)
                throw new ArgumentException(SR.GetString(SR.Error_EmptyArgument), "name");
 
            if (propertyType == null)
                throw new ArgumentNullException("propertyType");
 
            if (ownerType == null)
                throw new ArgumentNullException("ownerType");
 
            object defaultValue = null;
            if (propertyType.IsValueType)
            {
                try
                {
                    if (propertyType.IsEnum)
                    {
                        Array values = Enum.GetValues(propertyType);
                        if (values.Length > 0)
                            defaultValue = values.GetValue(0);
                        else
                            defaultValue = Activator.CreateInstance(propertyType);
                    }
                    else
                        defaultValue = Activator.CreateInstance(propertyType);
                }
                catch
                {
                }
            }
            return defaultValue;
        }
 
        private DependencyProperty(string name, System.Type propertyType, System.Type ownerType, PropertyMetadata defaultMetadata, System.Type validatorType, bool isRegistered)
        {
            this.name = name;
            this.propertyType = propertyType;
            this.ownerType = ownerType;
            this.validatorType = validatorType;
            this.isRegistered = isRegistered;
            this.defaultMetadata = defaultMetadata;
            this.defaultMetadata.Seal(this, propertyType);
            this.isEvent = (typeof(System.Delegate).IsAssignableFrom(this.propertyType) && (this.defaultMetadata == null || (this.defaultMetadata.Options & DependencyPropertyOptions.DelegateProperty) == 0));
        }
 
        public bool IsEvent
        {
            get
            {
                return this.isEvent;
            }
        }
 
        public bool IsAttached
        {
            get
            {
                return !this.isRegistered;
            }
        }
 
        public string Name
        {
            get
            {
                return this.name;
            }
        }
 
        public System.Type PropertyType
        {
            get
            {
                return this.propertyType;
            }
        }
        public System.Type OwnerType
        {
            get
            {
                return this.ownerType;
            }
        }
 
        public PropertyMetadata DefaultMetadata
        {
            get
            {
                return this.defaultMetadata;
            }
        }
        public System.Type ValidatorType
        {
            get
            {
                return this.validatorType;
            }
        }
        internal byte KnownIndex
        {
            get
            {
                return this.knownIndex;
            }
            set
            {
                this.knownIndex = value;
            }
        }
        
        internal bool IsKnown
        {
            get
            {
                return (this.knownIndex != 0);
            }
        }
 
        internal PropertyValidity Validity
        {
            get
            {
                return IsKnown ? knownProperties[this.knownIndex].propertyValidity : PropertyValidity.Always;
            }
        }
 
        public override string ToString()
        {
            return this.name;
        }
 
        public override int GetHashCode()
        {
            // 
 
            Debug.Assert(this.name != null && this.ownerType != null);
            return (this.name.GetHashCode() ^ this.ownerType.GetHashCode());
        }
 
        #region ISerializable Members
 
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("type", this.ownerType);
            info.AddValue("name", this.name);
            info.SetType(typeof(DependencyPropertyReference));
        }
        #endregion
 
        [Serializable]
        private sealed class DependencyPropertyReference : IObjectReference
        {
            private Type type = null;
            private string name = null;
 
            public Object GetRealObject(StreamingContext context)
            {
                return DependencyProperty.FromName(this.name, this.type);
            }
        }
    }
}