EnumDataContract.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / Serialization / System / Runtime / Serialization / EnumDataContract.cs / 1 / EnumDataContract.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Runtime.Serialization
{ 
    using System;
    //using System.ServiceModel.Channels; 
    using System.Collections; 
    using System.Collections.Generic;
    using System.Globalization; 
    using System.Reflection;
    using System.Threading;
    using System.Text;
    using System.Xml; 
    using System.Security;
 
    internal sealed class EnumDataContract : DataContract 
    {
        ///  
        /// Critical - holds instance of CriticalHelper which keeps state that is cached statically for serialization.
        ///            Static fields are marked SecurityCritical or readonly to prevent
        ///            data from being modified or leaked to other components in appdomain.
        ///  
        [SecurityCritical]
        EnumDataContractCriticalHelper helper; 
 
        /// 
        /// Critical - initializes SecurityCritical field 'helper' 
        /// Safe - doesn't leak anything
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal EnumDataContract() : base(new EnumDataContractCriticalHelper()) 
        {
            helper = base.Helper as EnumDataContractCriticalHelper; 
        } 

        ///  
        /// Critical - initializes SecurityCritical field 'helper'
        /// Safe - doesn't leak anything
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal EnumDataContract(Type type) : base(new EnumDataContractCriticalHelper(type))
        { 
            helper = base.Helper as EnumDataContractCriticalHelper; 
        }
 
        /// 
        /// Critical - accesses SecurityCritical static cache to look up base contract name for a type
        /// Safe - read only access
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        static internal XmlQualifiedName GetBaseContractName(Type type) 
        { 
            return EnumDataContractCriticalHelper.GetBaseContractName(type);
        } 

        /// 
        /// Critical - accesses SecurityCritical static cache to look up type for a base contract name
        /// Safe - read only access 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        static internal Type GetBaseType(XmlQualifiedName baseContractName) 
        {
            return EnumDataContractCriticalHelper.GetBaseType(baseContractName); 
        }

        internal XmlQualifiedName BaseContractName
        { 
            /// 
            /// Critical - fetches the critical BaseContractName property 
            /// Safe - BaseContractName only needs to be protected for write 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            get { return helper.BaseContractName; }
            /// 
            /// Critical - sets the critical BaseContractName property
            ///  
            [SecurityCritical]
            set { helper.BaseContractName = value; } 
        } 

        internal List Members 
        {
            /// 
            /// Critical - fetches the critical Members property
            /// Safe - Members only needs to be protected for write 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            get { return helper.Members; } 
            /// 
            /// Critical - sets the critical Members property 
            /// 
            [SecurityCritical]
            set { helper.Members = value; }
        } 

        internal List Values 
        { 
            /// 
            /// Critical - fetches the critical Values property 
            /// Safe - Values only needs to be protected for write
            /// 
            [SecurityCritical, SecurityTreatAsSafe]
            get { return helper.Values; } 
            /// 
            /// Critical - sets the critical Values property 
            ///  
            [SecurityCritical]
            set { helper.Values = value; } 
        }

        internal bool IsFlags
        { 
            /// 
            /// Critical - fetches the critical IsFlags property 
            /// Safe - IsFlags only needs to be protected for write 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            get { return helper.IsFlags; }
            /// 
            /// Critical - sets the critical IsFlags property
            ///  
            [SecurityCritical]
            set { helper.IsFlags = value; } 
        } 

        internal bool IsULong 
        {
            /// 
            /// Critical - fetches the critical IsULong property
            /// Safe - IsULong only needs to be protected for write 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            get { return helper.IsULong; } 
        }
 
        XmlDictionaryString[] ChildElementNames
        {
            /// 
            /// Critical - fetches the critical ChildElementNames property 
            /// Safe - ChildElementNames only needs to be protected for write
            ///  
            [SecurityCritical, SecurityTreatAsSafe] 
            get { return helper.ChildElementNames; }
        } 

        internal override bool CanContainReferences
        {
            get { return false; } 
        }
 
        ///  
        /// Critical - holds all state used for (de)serializing enums.
        ///            since the data is cached statically, we lock down access to it. 
        /// 
        [SecurityCritical(SecurityCriticalScope.Everything)]
        class EnumDataContractCriticalHelper : DataContract.DataContractCriticalHelper
        { 
            static Dictionary typeToName;
            static Dictionary nameToType; 
 
            XmlQualifiedName baseContractName;
            List members; 
            List values;
            bool isULong;
            bool isFlags;
            bool hasDataContract; 
            XmlDictionaryString[] childElementNames;
 
            static EnumDataContractCriticalHelper() 
            {
                typeToName = new Dictionary(); 
                nameToType = new Dictionary();
                Add(typeof(sbyte), "byte");
                Add(typeof(byte), "unsignedByte");
                Add(typeof(short), "short"); 
                Add(typeof(ushort), "unsignedShort");
                Add(typeof(int), "int"); 
                Add(typeof(uint), "unsignedInt"); 
                Add(typeof(long), "long");
                Add(typeof(ulong), "unsignedLong"); 
            }

            static internal void Add(Type type, string localName)
            { 
                XmlQualifiedName stableName = CreateQualifiedName(localName, Globals.SchemaNamespace);
                typeToName.Add(type, stableName); 
                nameToType.Add(stableName, type); 
            }
 
            static internal XmlQualifiedName GetBaseContractName(Type type)
            {
                XmlQualifiedName retVal = null;
                typeToName.TryGetValue(type, out retVal); 
                return retVal;
            } 
 
            static internal Type GetBaseType(XmlQualifiedName baseContractName)
            { 
                Type retVal = null;
                nameToType.TryGetValue(baseContractName, out retVal);
                return retVal;
            } 

            internal EnumDataContractCriticalHelper() 
            { 
                IsValueType = true;
            } 

            internal EnumDataContractCriticalHelper(Type type) : base(type)
            {
                this.StableName = DataContract.GetStableName(type, out hasDataContract); 
                Type baseType = Enum.GetUnderlyingType(type);
                baseContractName = GetBaseContractName(baseType); 
                ImportBaseType(baseType); 
                IsFlags = type.IsDefined(Globals.TypeOfFlagsAttribute, false);
                ImportDataMembers(); 

                XmlDictionary dictionary = new XmlDictionary(2 + Members.Count);
                Name = dictionary.Add(StableName.Name);
                Namespace = dictionary.Add(StableName.Namespace); 
                childElementNames = new XmlDictionaryString[Members.Count];
                for (int i = 0; i < Members.Count; i++) 
                    childElementNames[i] = dictionary.Add(Members[i].Name); 

                DataContractAttribute dataContractAttribute; 
                if (TryGetDCAttribute(type, out dataContractAttribute))
                {
                    if (dataContractAttribute.IsReference)
                    { 
                        DataContract.ThrowInvalidDataContractException(
                                SR.GetString(SR.EnumTypeCannotHaveIsReference, 
                                    DataContract.GetClrTypeFullName(type), 
                                    dataContractAttribute.IsReference,
                                    false), 
                                type);
                    }
                }
            } 

            internal XmlQualifiedName BaseContractName 
            { 
                get
                { 
                    return baseContractName;
                }
                set
                { 
                    baseContractName = value;
                    Type baseType = GetBaseType(baseContractName); 
                    if (baseType == null) 
                        ThrowInvalidDataContractException(SR.GetString(SR.InvalidEnumBaseType, value.Name, value.Namespace, StableName.Name, StableName.Namespace));
                    ImportBaseType(baseType); 
                }
            }

            internal List Members 
            {
                get { return members; } 
                set { members = value; } 
            }
 
            internal List Values
            {
                get { return values; }
                set { values = value; } 
            }
 
            internal bool IsFlags 
            {
                get { return isFlags; } 
                set { isFlags = value; }
            }

            internal bool IsULong 
            {
                get { return isULong; } 
            } 

            internal XmlDictionaryString[] ChildElementNames 
            {
                get { return childElementNames; }
            }
 
            void ImportBaseType(Type baseType)
            { 
                isULong = (baseType == Globals.TypeOfULong); 
            }
 
            void ImportDataMembers()
            {
                Type type = this.UnderlyingType;
                FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); 
                Dictionary memberValuesTable = new Dictionary();
                List tempMembers = new List(fields.Length); 
                List tempValues = new List(fields.Length); 

                for (int i = 0; i < fields.Length; i++) 
                {
                    FieldInfo field = fields[i];
                    bool enumMemberValid = false;
                    if (hasDataContract) 
                    {
                        object[] memberAttributes = field.GetCustomAttributes(Globals.TypeOfEnumMemberAttribute, false); 
                        if (memberAttributes != null && memberAttributes.Length > 0) 
                        {
                            if (memberAttributes.Length > 1) 
                                ThrowInvalidDataContractException(SR.GetString(SR.TooManyEnumMembers, DataContract.GetClrTypeFullName(field.DeclaringType), field.Name));
                            EnumMemberAttribute memberAttribute = (EnumMemberAttribute)memberAttributes[0];

                            DataMember memberContract = new DataMember(field); 
                            if (memberAttribute.IsValueSetExplicit)
                            { 
                                if (memberAttribute.Value == null || memberAttribute.Value.Length == 0) 
                                    ThrowInvalidDataContractException(SR.GetString(SR.InvalidEnumMemberValue, field.Name, DataContract.GetClrTypeFullName(type)));
                                memberContract.Name = memberAttribute.Value; 
                            }
                            else
                                memberContract.Name = field.Name;
                            ClassDataContract.CheckAndAddMember(tempMembers, memberContract, memberValuesTable); 
                            enumMemberValid = true;
                        } 
 
                        object[] dataMemberAttributes = field.GetCustomAttributes(Globals.TypeOfDataMemberAttribute, false);
                        if (dataMemberAttributes != null && dataMemberAttributes.Length > 0) 
                            ThrowInvalidDataContractException(SR.GetString(SR.DataMemberOnEnumField, DataContract.GetClrTypeFullName(field.DeclaringType), field.Name));
                    }
                    else
                    { 
                        if (!field.IsNotSerialized)
                        { 
                            DataMember memberContract = new DataMember(field); 
                            memberContract.Name = field.Name;
                            ClassDataContract.CheckAndAddMember(tempMembers, memberContract, memberValuesTable); 
                            enumMemberValid = true;
                        }
                    }
 
                    if (enumMemberValid)
                    { 
                        object enumValue = field.GetValue(null); 
                        if (isULong)
                            tempValues.Add((long)((IConvertible)enumValue).ToUInt64(null)); 
                        else
                            tempValues.Add(((IConvertible)enumValue).ToInt64(null));
                    }
                } 

                Thread.MemoryBarrier(); 
                members = tempMembers; 
                values = tempValues;
            } 
        }

        internal void WriteEnumValue(XmlWriterDelegator writer, object value)
        { 
            long longValue = IsULong ? (long)((IConvertible)value).ToUInt64(null) : ((IConvertible)value).ToInt64(null);
            for (int i = 0; i < Values.Count; i++) 
            { 
                if (longValue == Values[i])
                { 
                    writer.WriteString(ChildElementNames[i].Value);
                    return;
                }
            } 
            if (IsFlags)
            { 
                int zeroIndex = -1; 
                bool noneWritten = true;
                for (int i = 0; i < Values.Count; i++) 
                {
                    long current = Values[i];
                    if (current == 0)
                    { 
                        zeroIndex = i;
                        continue; 
                    } 
                    if (longValue == 0)
                        break; 
                    if ((current & longValue) == current)
                    {
                        if (noneWritten)
                            noneWritten = false; 
                        else
                            writer.WriteString(DictionaryGlobals.Space.Value); 
 
                        writer.WriteString(ChildElementNames[i].Value);
                        longValue &= ~current; 
                    }
                }
                // enforce that enum value was completely parsed
                if (longValue != 0) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.InvalidEnumValueOnWrite, value, DataContract.GetClrTypeFullName(UnderlyingType))));
 
                if (noneWritten && zeroIndex >= 0) 
                    writer.WriteString(ChildElementNames[zeroIndex].Value);
            } 
            else
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.InvalidEnumValueOnWrite, value, DataContract.GetClrTypeFullName(UnderlyingType))));
        }
 
        internal object ReadEnumValue(XmlReaderDelegator reader)
        { 
            string stringValue = reader.ReadElementContentAsString(); 
            long longValue = 0;
            int i = 0; 
            if (IsFlags)
            {
                // Skip initial spaces
                for (; i < stringValue.Length; i++) 
                    if (stringValue[i] != ' ')
                        break; 
 
                // Read space-delimited values
                int startIndex = i; 
                int count = 0;
                for (; i < stringValue.Length; i++)
                {
                    if (stringValue[i] == ' ') 
                    {
                        count = i - startIndex; 
                        if (count > 0) 
                            longValue |= ReadEnumValue(stringValue, startIndex, count);
                        for (++i; i < stringValue.Length; i++) 
                            if (stringValue[i] != ' ')
                                break;
                        startIndex = i;
                        if (i == stringValue.Length) 
                            break;
                    } 
                } 
                count = i - startIndex;
                if (count > 0) 
                    longValue |= ReadEnumValue(stringValue, startIndex, count);
            }
            else
            { 
                if (stringValue.Length == 0)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.InvalidEnumValueOnRead, stringValue, DataContract.GetClrTypeFullName(UnderlyingType)))); 
                longValue = ReadEnumValue(stringValue, 0, stringValue.Length); 
            }
 
            if (IsULong)
                return Enum.ToObject(UnderlyingType, (ulong)longValue);
            return Enum.ToObject(UnderlyingType, longValue);
        } 

        long ReadEnumValue(string value, int index, int count) 
        { 
            for (int i = 0; i < Members.Count; i++)
            { 
                string memberName = Members[i].Name;
                if (memberName.Length == count && String.CompareOrdinal(value, index, memberName, 0, count) == 0)
                {
                    return Values[i]; 
                }
            } 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.InvalidEnumValueOnRead, value.Substring(index, count), DataContract.GetClrTypeFullName(UnderlyingType)))); 
        }
 
        internal string GetStringFromEnumValue(long value)
        {
            if (IsULong)
                return XmlConvert.ToString((ulong)value); 
            else
                return XmlConvert.ToString(value); 
        } 

        internal long GetEnumValueFromString(string value) 
        {
            if (IsULong)
                return (long) XmlConverter.ToUInt64(value);
            else 
                return XmlConverter.ToInt64(value);
        } 
 
        internal override bool Equals(object other, Dictionary checkedContracts)
        { 
            if (IsEqualOrChecked(other, checkedContracts))
                return true;

            if (base.Equals(other, null)) 
            {
                EnumDataContract dataContract = other as EnumDataContract; 
                if (dataContract != null) 
                {
                    if (Members.Count != dataContract.Members.Count || Values.Count != dataContract.Values.Count) 
                        return false;
                    string[] memberNames1 = new string[Members.Count], memberNames2 = new string[Members.Count];
                    for (int i = 0; i < Members.Count; i++)
                    { 
                        memberNames1[i] = Members[i].Name;
                        memberNames2[i] = dataContract.Members[i].Name; 
                    } 
                    Array.Sort(memberNames1);
                    Array.Sort(memberNames2); 
                    for (int i = 0; i < Members.Count; i++)
                    {
                        if (memberNames1[i] != memberNames2[i])
                            return false; 
                    }
 
                    return (IsFlags == dataContract.IsFlags); 
                }
            } 
            return false;
        }

        public override int GetHashCode() 
        {
            return base.GetHashCode(); 
        } 

        public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context) 
        {
            WriteEnumValue(xmlWriter, obj);
        }
 
        public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
        { 
            object obj = ReadEnumValue(xmlReader); 
            if (context != null)
                context.AddNewObject(obj); 
            return obj;
        }

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK