ResourceType.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataWeb / Server / System / Data / Services / Providers / ResourceType.cs / 1 / ResourceType.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Contains information about a particular resource.
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Providers
{
    #region Namespaces. 

    using System; 
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Text; 

    #endregion Namespaces.

    /// Use this class to represent a DataService type (primitive, complex or entity). 
    [DebuggerDisplay("{Type}: {ResourceTypeKind}")]
    internal class ResourceType 
    { 
        #region Fields.
 
        ///  empty list of properties 
        internal static readonly List EmptyProperties = new List(new ResourceProperty[0]);

#if ASTORIA_OPEN_OBJECT 

        /// Whether the resource type has open properties. 
        private readonly OpenTypeKind openTypeKind; 

#endif 

        ///  ResourceTypeKind for the type that this structure represents 
        private readonly ResourceTypeKind resourceTypeKind;
 
        ///  Reference to clr type that this resource represents 
        private readonly Type type; 
 
        ///  Reference to base resource type 
        private readonly ResourceType baseType; 

        ///  name of the resource.
        private readonly string name;
 
        ///  full name of the resource.
        private readonly string fullName; 
 
        /// Cached delegate to create a new instance of this type.
        private Func constructorDelegate; 

        /// Cached delegate to serialize parts of this resource into a dictionary.
        private Action dictionarySerializerDelegate;
 
        ///  List of properties for this type (includes properties only defined in this type, not in the base type) 
        private List properties; 
 
        ///  List of all properties for this type (includes properties defined in the base type also) 
        private List allProperties; 

        ///  list of key properties for this type
        private List keyProperties;
 
        ///  list of etag properties for this type.
        private List etagProperties; 
 
        ///  true if this type has some derived types
        private bool hasDerivedTypes; 

        #endregion Fields.

        #region Constructors. 

        ///  
        /// Constructs a new instance of Astoria type using the specified clr type 
        /// 
        /// clr type from which metadata needs to be pulled  
        ///  kind of the resource type
        internal ResourceType(Type type, ResourceTypeKind resourceTypeKind)
            : this(type, resourceTypeKind, null)
        { 
        }
 
        ///  
        /// Constructs a new instance of Astoria type using the specified clr type
        ///  
        /// clr type from which metadata needs to be pulled 
        ///  kind of the resource type
        /// base type of the resource type
        internal ResourceType(Type type, ResourceTypeKind resourceTypeKind, ResourceType baseType) 
            : this(type, resourceTypeKind, baseType, GetModelTypeFullName(type), GetModelTypeName(type))
        { 
        } 

        ///  
        /// Constructs a new instance of Astoria type using the specified clr type
        /// 
        /// clr type from which metadata needs to be pulled 
        ///  kind of the resource type 
        /// base type of the resource type
        /// full name of the given resource type. 
        /// name of the given resource type. 
        internal ResourceType(Type type, ResourceTypeKind resourceTypeKind, ResourceType baseType, string fullName, string name)
        { 
            Debug.Assert(type != null, "type must never be null");
            WebUtil.DebugEnumIsDefined(resourceTypeKind);

            this.name = name; 
            this.fullName = fullName;
            this.type = type; 
            this.resourceTypeKind = resourceTypeKind; 
#if ASTORIA_OPEN_OBJECT
            this.openTypeKind = CheckOpenType(type); 
#endif

            if (baseType != null)
            { 
                this.baseType = baseType;
                this.baseType.HasDerivedTypes = true; 
            } 
        }
 
        #endregion Constructors.

        #region Properties.
 
        /// Cached delegate to create a new instance of this type.
        internal Func ConstructorDelegate 
        { 
            get
            { 
                if (this.constructorDelegate == null)
                {
                    this.constructorDelegate = (Func)
                        WebUtil.CreateNewInstanceConstructor(this.Type, this.FullName, typeof(object)); 
                }
 
                return this.constructorDelegate; 
            }
        } 

        /// Cached delegate to serialize parts of this resource into a dictionary.
        internal Action DictionarySerializerDelegate
        { 
            get { return this.dictionarySerializerDelegate; }
            set { this.dictionarySerializerDelegate = value; } 
        } 

        ///  Reference to clr type that this resource represents  
        internal Type Type
        {
            [DebuggerStepThrough]
            get { return this.type; } 
        }
 
        ///  Reference to base resource type, if any  
        internal ResourceType BaseType
        { 
            [DebuggerStepThrough]
            get { return this.baseType; }
        }
 
#if ASTORIA_OPEN_OBJECT
 
        /// Whether the resource type has open properties. 
        internal bool IsOpenType
        { 
            [DebuggerStepThrough]
            get { return this.openTypeKind != System.Data.Services.OpenTypeKind.NotAnOpenType; }
        }
 
        /// returns the kind of open type this type represents.
        internal OpenTypeKind OpenTypeKind 
        { 
            [DebuggerStepThrough]
            get { return this.openTypeKind; } 
        }

#endif
 
        ///  ResourceTypeKind of this type 
        internal ResourceTypeKind ResourceTypeKind 
        { 
            [DebuggerStepThrough]
            get { return this.resourceTypeKind; } 
        }

        ///  Returns the list of properties for this type 
        internal List Properties 
        {
            get 
            { 
                if (this.allProperties == null)
                { 
                    if (this.BaseType == null)
                    {
                        this.allProperties = this.PropertiesDeclaredInThisType;
                    } 
                    else if (this.PropertiesDeclaredInThisType.Count == 0)
                    { 
                        this.allProperties = this.BaseType.Properties; 
                    }
                    else 
                    {
                        List all = new List(this.BaseType.Properties.Count + this.PropertiesDeclaredInThisType.Count);
                        all.AddRange(this.BaseType.Properties);
                        all.AddRange(this.PropertiesDeclaredInThisType); 
                        this.allProperties = all;
                    } 
                } 

                // This assert takes care that we don't update the properties list after caching 
                Debug.Assert(
                    this.allProperties.Count == (this.BaseType == null
                        ? this.PropertiesDeclaredInThisType.Count
                        : (this.BaseType.Properties.Count + this.PropertiesDeclaredInThisType.Count)), 
                    "Properties can be updated after its cached");
                return this.allProperties; 
            } 
        }
 
        ///  list of properties declared on this type 
        internal List PropertiesDeclaredInThisType
        {
            get 
            {
                if (this.properties == null) 
                { 
                    this.properties = ResourceType.EmptyProperties;
                } 

                return this.properties;
            }
        } 

        ///  Returns the list of key properties for this type, if this type is entity type  
        internal List KeyProperties 
        {
            get 
            {
                // Populate this when you access for the first time,
                // so we don't walk down the hierarchy every single time.
                if (this.keyProperties == null) 
                {
                    ResourceType rootType = this; 
                    while (rootType.BaseType != null) 
                    {
                        rootType = rootType.BaseType; 
                    }

                    this.keyProperties = rootType.keyProperties;
                } 

                return this.keyProperties; 
            } 
        }
 
        /// Returns the list of etag properties for this type.
        internal List ETagProperties
        {
            get 
            {
                if (this.etagProperties == null) 
                { 
                    if (this.BaseType != null)
                    { 
                        this.etagProperties = this.BaseType.ETagProperties;
                    }
                    else
                    { 
                        this.etagProperties = ResourceType.EmptyProperties;
                    } 
                } 

                return this.etagProperties; 
            }
        }

        ///  Gets the name of the resource. 
        internal string Name
        { 
            get { return this.name; } 
        }
 
        ///  Gets the fullname of the resource.
        internal string FullName
        {
            get { return this.fullName; } 
        }
 
        ///  true if this type has some derived types 
        internal bool HasDerivedTypes
        { 
            get
            {
                return this.hasDerivedTypes;
            } 

            set 
            { 
                Debug.Assert(value != false, "This should never be set to false");
                this.hasDerivedTypes = value; 
            }
        }

        #endregion Properties. 

        #region Methods. 
 
        /// 
        /// Adds the given property to the baseType 
        /// 
        /// resource property to be added
        internal void AddProperty(ResourceProperty resourceProperty)
        { 
            if (this.properties == null)
            { 
                this.properties = new List(); 
            }
 
            // There can be properties with the same name in the base class also (using the new construct)
            // if the base type is not null, then we need to make sure that there is no property with the same name.
            // Otherwise, we are only populating property declared for this type and clr gaurantees that they are unique
            if (this.BaseType != null) 
            {
                foreach (ResourceProperty rp in this.BaseType.Properties) 
                { 
                    if (rp.Name == resourceProperty.Name)
                    { 
                        throw new InvalidOperationException(Strings.ReflectionProvider_PropertyWithSameNameAlreadyExists(rp.Name, this.FullName));
                    }
                }
            } 
            else
            { 
                foreach (ResourceProperty rp in this.properties) 
                {
                    if (rp.Name == resourceProperty.Name) 
                    {
                        throw new InvalidOperationException(Strings.ReflectionProvider_PropertyWithSameNameAlreadyExists(rp.Name, this.FullName));
                    }
                } 
            }
 
            this.properties.Add(resourceProperty); 

            if (resourceProperty.IsOfKind(ResourcePropertyKind.Key)) 
            {
                Debug.Assert(this.baseType == null, "You cannot have a key property if baseType is not null");
                if (this.keyProperties == null)
                { 
                    this.keyProperties = new List();
                } 
 
                this.KeyProperties.Add(resourceProperty);
            } 
        }

        /// 
        /// Add the given property to the etag properties. 
        /// 
        /// resource property to be added as etag property. 
        internal void AddETagProperty(ResourceProperty resourceProperty) 
        {
            Debug.Assert(resourceProperty.TypeKind == ResourceTypeKind.Primitive, "Only Primitive are allowed as etag properties"); 
            bool baseTypeContainsETag = (this.BaseType != null && this.BaseType.ETagProperties != null);
            Debug.Assert(this.PropertiesDeclaredInThisType.Contains(resourceProperty) || !baseTypeContainsETag, "the property must be defined for this type");

            if (this.etagProperties == null) 
            {
                this.etagProperties = new List(); 
                if (baseTypeContainsETag) 
                {
                    // Add the etag properties of the base type to this type. 
                    this.etagProperties.AddRange(this.baseType.ETagProperties);
                }
            }
 
            // Add the given property to the etag properties.
            this.etagProperties.Add(resourceProperty); 
        } 

        ///  
        /// Sorts the key members in the aplhabatical order
        /// 
        internal void SortKeyMembers()
        { 
            if (this.KeyProperties != null)
            { 
                this.KeyProperties.Sort(ResourcePropertyComparison); 
            }
        } 

        /// 
        /// Changes the key property to non key property and removes it from the key properties list
        ///  
        internal void RemoveKeyProperties()
        { 
            Debug.Assert(this.KeyProperties.Count == 1, "Key Properties count must be zero"); 
            Debug.Assert(this.BaseType == null, "BaseType must be null");
            Debug.Assert(this.KeyProperties[0].IsOfKind(ResourcePropertyKind.Key), "must be key property"); 

            ResourceProperty property = this.keyProperties[0];
            property.Kind = property.Kind ^ ResourcePropertyKind.Key;
            this.keyProperties.Clear(); 
        }
 
        /// Trims excess capacity from all collections. 
        internal void TrimExcess()
        { 
            TrimExcessFromList(this.allProperties);
            TrimExcessFromList(this.etagProperties);
            TrimExcessFromList(this.keyProperties);
            TrimExcessFromList(this.properties); 
        }
 
        /// Tries to find the property for the specified name. 
        /// Name of property to resolve.
        /// Resolved property; possibly null. 
        internal ResourceProperty TryResolvePropertyName(string propertyName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");
 
            foreach (ResourceProperty typeProperty in this.Properties)
            { 
                if (typeProperty.Name == propertyName) 
                {
                    return typeProperty; 
                }
            }

            return null; 
        }
 
        /// Tries to find the property for the specified name. 
        /// Name of property to resolve.
        /// Resolved property; possibly null. 
        internal ResourceProperty TryResolvePropertyNameDefinedInThisType(string propertyName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");
 
            foreach (ResourceProperty typeProperty in this.PropertiesDeclaredInThisType)
            { 
                if (typeProperty.Name == propertyName) 
                {
                    return typeProperty; 
                }
            }

            return null; 
        }
 
        ///  
        /// Checks whether the resource type has navigation properties or not.
        ///  
        /// Returns true if the resource type has one or more navigation properties. Otherwise returns false.
        internal bool HasNavigationProperties()
        {
            return this.PropertiesDeclaredInThisType.Exists(p => p.TypeKind == ResourceTypeKind.EntityType); 
        }
 
        ///  
        /// Compares two resource property instances, sorting them so keys are first,
        /// and are alphabetically ordered in case-insensitive ordinal order. 
        /// 
        /// First property to compare.
        /// Second property to compare.
        ///  
        /// Less than zero if a sorts before b; zero if equal; greater than zero if a sorts
        /// after b. 
        ///  
        protected static int ResourcePropertyComparison(ResourceProperty a, ResourceProperty b)
        { 
            return StringComparer.OrdinalIgnoreCase.Compare(a.Name, b.Name);
        }

#if ASTORIA_OPEN_OBJECT 

        /// Checks whether the specified  is an open type. 
        /// Type to check. 
        /// true if  is an open type; false otherwise.
        ///  
        /// Thrown when the type is declared as an open type but the declared
        /// property isn't there or doesn't support name/value pairs.
        /// 
        private static OpenTypeKind CheckOpenType(Type type) 
        {
            if (!OpenTypeAttribute.IsOpenType(type)) 
            { 
                return OpenTypeKind.NotAnOpenType;
            } 

            OpenTypeKind openTypeKind = OpenTypeAttribute.IsOpenPropertyAvailable(type);
            if (openTypeKind == OpenTypeKind.NotAnOpenType)
            { 
                throw new InvalidOperationException(Strings.ResourceType_IncorrectOpenProperty(type));
            } 
 
            return openTypeKind;
        } 
#endif

        /// 
        /// Gets the namespace-qualified type name of the specified , 
        /// appropriate as an externally-visible type name.
        ///  
        /// Type to get name for. 
        /// The namespace-qualified type name for .
        ///  
        /// Where do type names show up?
        /// - CSDL document. Need namespace and name that are simple names.
        /// - ATOM attributes. Need namespace and name as well.
        /// 
        /// Some sample name mappings:
        /// - System.String          -> Edm.String  -- NYI, but the 'GetModel' family of methods would be correct place to add support 
        /// - System.Uri             -> System.Uri 
        /// - Custom.Client          -> Custom.Client
        /// - Custom.Client+Address  -> Custom.Client_Address 
        /// 
        private static string GetModelTypeFullName(Type type)
        {
            Debug.Assert(type != null, "type != null"); 
            string typeNamespace = WebUtil.GetModelTypeNamespace(type);
            string typeName = GetModelTypeName(type); 
            if (String.IsNullOrEmpty(typeNamespace)) 
            {
                return typeName; 
            }
            else
            {
                return typeNamespace + "." + typeName; 
            }
        } 
 
        /// 
        /// Gets the type name (without namespace) of the specified , 
        /// appropriate as an externally-visible type name.
        /// 
        /// Type to get name for.
        /// The type name for . 
        private static string GetModelTypeName(Type type)
        { 
            Debug.Assert(type != null, "type != null"); 
            if (type.IsGenericType)
            { 
                Type[] genericArguments = type.GetGenericArguments();
                StringBuilder builder = new StringBuilder(type.Name.Length * 2 * (1 + genericArguments.Length));
                if (type.IsNested)
                { 
                    Debug.Assert(type.DeclaringType != null, "type.DeclaringType != null");
                    builder.Append(GetModelTypeName(type.DeclaringType)); 
                    builder.Append('_'); 
                }
 
                builder.Append(type.Name);
                builder.Append('[');
                for (int i = 0; i < genericArguments.Length; i++)
                { 
                    if (i > 0)
                    { 
                        builder.Append(' '); 
                    }
 
                    string genericNamespace = WebUtil.GetModelTypeNamespace(genericArguments[i]);
                    if (!String.IsNullOrEmpty(genericNamespace))
                    {
                        builder.Append(genericNamespace); 
                        builder.Append('.');
                    } 
 
                    builder.Append(GetModelTypeName(genericArguments[i]));
                } 

                builder.Append(']');
                return builder.ToString();
            } 
            else if (type.IsNested)
            { 
                Debug.Assert(type.DeclaringType != null, "type.DeclaringType != null"); 
                return GetModelTypeName(type.DeclaringType) + "_" + type.Name;
            } 
            else
            {
                return type.Name;
            } 
        }
 
        ///  
        /// Sets the capacity to the actual number of elements in the List, if the list is not null and
        /// that number is less than a threshold value. 
        /// 
        /// The type of elements in the list.
        /// List to trim excess from (possibly null).
        private static void TrimExcessFromList(List list) 
        {
            if (list != null && list.Capacity > 0) 
            { 
                list.TrimExcess();
            } 
        }

        #endregion Methods.
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Contains information about a particular resource.
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Providers
{
    #region Namespaces. 

    using System; 
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Text; 

    #endregion Namespaces.

    /// Use this class to represent a DataService type (primitive, complex or entity). 
    [DebuggerDisplay("{Type}: {ResourceTypeKind}")]
    internal class ResourceType 
    { 
        #region Fields.
 
        ///  empty list of properties 
        internal static readonly List EmptyProperties = new List(new ResourceProperty[0]);

#if ASTORIA_OPEN_OBJECT 

        /// Whether the resource type has open properties. 
        private readonly OpenTypeKind openTypeKind; 

#endif 

        ///  ResourceTypeKind for the type that this structure represents 
        private readonly ResourceTypeKind resourceTypeKind;
 
        ///  Reference to clr type that this resource represents 
        private readonly Type type; 
 
        ///  Reference to base resource type 
        private readonly ResourceType baseType; 

        ///  name of the resource.
        private readonly string name;
 
        ///  full name of the resource.
        private readonly string fullName; 
 
        /// Cached delegate to create a new instance of this type.
        private Func constructorDelegate; 

        /// Cached delegate to serialize parts of this resource into a dictionary.
        private Action dictionarySerializerDelegate;
 
        ///  List of properties for this type (includes properties only defined in this type, not in the base type) 
        private List properties; 
 
        ///  List of all properties for this type (includes properties defined in the base type also) 
        private List allProperties; 

        ///  list of key properties for this type
        private List keyProperties;
 
        ///  list of etag properties for this type.
        private List etagProperties; 
 
        ///  true if this type has some derived types
        private bool hasDerivedTypes; 

        #endregion Fields.

        #region Constructors. 

        ///  
        /// Constructs a new instance of Astoria type using the specified clr type 
        /// 
        /// clr type from which metadata needs to be pulled  
        ///  kind of the resource type
        internal ResourceType(Type type, ResourceTypeKind resourceTypeKind)
            : this(type, resourceTypeKind, null)
        { 
        }
 
        ///  
        /// Constructs a new instance of Astoria type using the specified clr type
        ///  
        /// clr type from which metadata needs to be pulled 
        ///  kind of the resource type
        /// base type of the resource type
        internal ResourceType(Type type, ResourceTypeKind resourceTypeKind, ResourceType baseType) 
            : this(type, resourceTypeKind, baseType, GetModelTypeFullName(type), GetModelTypeName(type))
        { 
        } 

        ///  
        /// Constructs a new instance of Astoria type using the specified clr type
        /// 
        /// clr type from which metadata needs to be pulled 
        ///  kind of the resource type 
        /// base type of the resource type
        /// full name of the given resource type. 
        /// name of the given resource type. 
        internal ResourceType(Type type, ResourceTypeKind resourceTypeKind, ResourceType baseType, string fullName, string name)
        { 
            Debug.Assert(type != null, "type must never be null");
            WebUtil.DebugEnumIsDefined(resourceTypeKind);

            this.name = name; 
            this.fullName = fullName;
            this.type = type; 
            this.resourceTypeKind = resourceTypeKind; 
#if ASTORIA_OPEN_OBJECT
            this.openTypeKind = CheckOpenType(type); 
#endif

            if (baseType != null)
            { 
                this.baseType = baseType;
                this.baseType.HasDerivedTypes = true; 
            } 
        }
 
        #endregion Constructors.

        #region Properties.
 
        /// Cached delegate to create a new instance of this type.
        internal Func ConstructorDelegate 
        { 
            get
            { 
                if (this.constructorDelegate == null)
                {
                    this.constructorDelegate = (Func)
                        WebUtil.CreateNewInstanceConstructor(this.Type, this.FullName, typeof(object)); 
                }
 
                return this.constructorDelegate; 
            }
        } 

        /// Cached delegate to serialize parts of this resource into a dictionary.
        internal Action DictionarySerializerDelegate
        { 
            get { return this.dictionarySerializerDelegate; }
            set { this.dictionarySerializerDelegate = value; } 
        } 

        ///  Reference to clr type that this resource represents  
        internal Type Type
        {
            [DebuggerStepThrough]
            get { return this.type; } 
        }
 
        ///  Reference to base resource type, if any  
        internal ResourceType BaseType
        { 
            [DebuggerStepThrough]
            get { return this.baseType; }
        }
 
#if ASTORIA_OPEN_OBJECT
 
        /// Whether the resource type has open properties. 
        internal bool IsOpenType
        { 
            [DebuggerStepThrough]
            get { return this.openTypeKind != System.Data.Services.OpenTypeKind.NotAnOpenType; }
        }
 
        /// returns the kind of open type this type represents.
        internal OpenTypeKind OpenTypeKind 
        { 
            [DebuggerStepThrough]
            get { return this.openTypeKind; } 
        }

#endif
 
        ///  ResourceTypeKind of this type 
        internal ResourceTypeKind ResourceTypeKind 
        { 
            [DebuggerStepThrough]
            get { return this.resourceTypeKind; } 
        }

        ///  Returns the list of properties for this type 
        internal List Properties 
        {
            get 
            { 
                if (this.allProperties == null)
                { 
                    if (this.BaseType == null)
                    {
                        this.allProperties = this.PropertiesDeclaredInThisType;
                    } 
                    else if (this.PropertiesDeclaredInThisType.Count == 0)
                    { 
                        this.allProperties = this.BaseType.Properties; 
                    }
                    else 
                    {
                        List all = new List(this.BaseType.Properties.Count + this.PropertiesDeclaredInThisType.Count);
                        all.AddRange(this.BaseType.Properties);
                        all.AddRange(this.PropertiesDeclaredInThisType); 
                        this.allProperties = all;
                    } 
                } 

                // This assert takes care that we don't update the properties list after caching 
                Debug.Assert(
                    this.allProperties.Count == (this.BaseType == null
                        ? this.PropertiesDeclaredInThisType.Count
                        : (this.BaseType.Properties.Count + this.PropertiesDeclaredInThisType.Count)), 
                    "Properties can be updated after its cached");
                return this.allProperties; 
            } 
        }
 
        ///  list of properties declared on this type 
        internal List PropertiesDeclaredInThisType
        {
            get 
            {
                if (this.properties == null) 
                { 
                    this.properties = ResourceType.EmptyProperties;
                } 

                return this.properties;
            }
        } 

        ///  Returns the list of key properties for this type, if this type is entity type  
        internal List KeyProperties 
        {
            get 
            {
                // Populate this when you access for the first time,
                // so we don't walk down the hierarchy every single time.
                if (this.keyProperties == null) 
                {
                    ResourceType rootType = this; 
                    while (rootType.BaseType != null) 
                    {
                        rootType = rootType.BaseType; 
                    }

                    this.keyProperties = rootType.keyProperties;
                } 

                return this.keyProperties; 
            } 
        }
 
        /// Returns the list of etag properties for this type.
        internal List ETagProperties
        {
            get 
            {
                if (this.etagProperties == null) 
                { 
                    if (this.BaseType != null)
                    { 
                        this.etagProperties = this.BaseType.ETagProperties;
                    }
                    else
                    { 
                        this.etagProperties = ResourceType.EmptyProperties;
                    } 
                } 

                return this.etagProperties; 
            }
        }

        ///  Gets the name of the resource. 
        internal string Name
        { 
            get { return this.name; } 
        }
 
        ///  Gets the fullname of the resource.
        internal string FullName
        {
            get { return this.fullName; } 
        }
 
        ///  true if this type has some derived types 
        internal bool HasDerivedTypes
        { 
            get
            {
                return this.hasDerivedTypes;
            } 

            set 
            { 
                Debug.Assert(value != false, "This should never be set to false");
                this.hasDerivedTypes = value; 
            }
        }

        #endregion Properties. 

        #region Methods. 
 
        /// 
        /// Adds the given property to the baseType 
        /// 
        /// resource property to be added
        internal void AddProperty(ResourceProperty resourceProperty)
        { 
            if (this.properties == null)
            { 
                this.properties = new List(); 
            }
 
            // There can be properties with the same name in the base class also (using the new construct)
            // if the base type is not null, then we need to make sure that there is no property with the same name.
            // Otherwise, we are only populating property declared for this type and clr gaurantees that they are unique
            if (this.BaseType != null) 
            {
                foreach (ResourceProperty rp in this.BaseType.Properties) 
                { 
                    if (rp.Name == resourceProperty.Name)
                    { 
                        throw new InvalidOperationException(Strings.ReflectionProvider_PropertyWithSameNameAlreadyExists(rp.Name, this.FullName));
                    }
                }
            } 
            else
            { 
                foreach (ResourceProperty rp in this.properties) 
                {
                    if (rp.Name == resourceProperty.Name) 
                    {
                        throw new InvalidOperationException(Strings.ReflectionProvider_PropertyWithSameNameAlreadyExists(rp.Name, this.FullName));
                    }
                } 
            }
 
            this.properties.Add(resourceProperty); 

            if (resourceProperty.IsOfKind(ResourcePropertyKind.Key)) 
            {
                Debug.Assert(this.baseType == null, "You cannot have a key property if baseType is not null");
                if (this.keyProperties == null)
                { 
                    this.keyProperties = new List();
                } 
 
                this.KeyProperties.Add(resourceProperty);
            } 
        }

        /// 
        /// Add the given property to the etag properties. 
        /// 
        /// resource property to be added as etag property. 
        internal void AddETagProperty(ResourceProperty resourceProperty) 
        {
            Debug.Assert(resourceProperty.TypeKind == ResourceTypeKind.Primitive, "Only Primitive are allowed as etag properties"); 
            bool baseTypeContainsETag = (this.BaseType != null && this.BaseType.ETagProperties != null);
            Debug.Assert(this.PropertiesDeclaredInThisType.Contains(resourceProperty) || !baseTypeContainsETag, "the property must be defined for this type");

            if (this.etagProperties == null) 
            {
                this.etagProperties = new List(); 
                if (baseTypeContainsETag) 
                {
                    // Add the etag properties of the base type to this type. 
                    this.etagProperties.AddRange(this.baseType.ETagProperties);
                }
            }
 
            // Add the given property to the etag properties.
            this.etagProperties.Add(resourceProperty); 
        } 

        ///  
        /// Sorts the key members in the aplhabatical order
        /// 
        internal void SortKeyMembers()
        { 
            if (this.KeyProperties != null)
            { 
                this.KeyProperties.Sort(ResourcePropertyComparison); 
            }
        } 

        /// 
        /// Changes the key property to non key property and removes it from the key properties list
        ///  
        internal void RemoveKeyProperties()
        { 
            Debug.Assert(this.KeyProperties.Count == 1, "Key Properties count must be zero"); 
            Debug.Assert(this.BaseType == null, "BaseType must be null");
            Debug.Assert(this.KeyProperties[0].IsOfKind(ResourcePropertyKind.Key), "must be key property"); 

            ResourceProperty property = this.keyProperties[0];
            property.Kind = property.Kind ^ ResourcePropertyKind.Key;
            this.keyProperties.Clear(); 
        }
 
        /// Trims excess capacity from all collections. 
        internal void TrimExcess()
        { 
            TrimExcessFromList(this.allProperties);
            TrimExcessFromList(this.etagProperties);
            TrimExcessFromList(this.keyProperties);
            TrimExcessFromList(this.properties); 
        }
 
        /// Tries to find the property for the specified name. 
        /// Name of property to resolve.
        /// Resolved property; possibly null. 
        internal ResourceProperty TryResolvePropertyName(string propertyName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");
 
            foreach (ResourceProperty typeProperty in this.Properties)
            { 
                if (typeProperty.Name == propertyName) 
                {
                    return typeProperty; 
                }
            }

            return null; 
        }
 
        /// Tries to find the property for the specified name. 
        /// Name of property to resolve.
        /// Resolved property; possibly null. 
        internal ResourceProperty TryResolvePropertyNameDefinedInThisType(string propertyName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");
 
            foreach (ResourceProperty typeProperty in this.PropertiesDeclaredInThisType)
            { 
                if (typeProperty.Name == propertyName) 
                {
                    return typeProperty; 
                }
            }

            return null; 
        }
 
        ///  
        /// Checks whether the resource type has navigation properties or not.
        ///  
        /// Returns true if the resource type has one or more navigation properties. Otherwise returns false.
        internal bool HasNavigationProperties()
        {
            return this.PropertiesDeclaredInThisType.Exists(p => p.TypeKind == ResourceTypeKind.EntityType); 
        }
 
        ///  
        /// Compares two resource property instances, sorting them so keys are first,
        /// and are alphabetically ordered in case-insensitive ordinal order. 
        /// 
        /// First property to compare.
        /// Second property to compare.
        ///  
        /// Less than zero if a sorts before b; zero if equal; greater than zero if a sorts
        /// after b. 
        ///  
        protected static int ResourcePropertyComparison(ResourceProperty a, ResourceProperty b)
        { 
            return StringComparer.OrdinalIgnoreCase.Compare(a.Name, b.Name);
        }

#if ASTORIA_OPEN_OBJECT 

        /// Checks whether the specified  is an open type. 
        /// Type to check. 
        /// true if  is an open type; false otherwise.
        ///  
        /// Thrown when the type is declared as an open type but the declared
        /// property isn't there or doesn't support name/value pairs.
        /// 
        private static OpenTypeKind CheckOpenType(Type type) 
        {
            if (!OpenTypeAttribute.IsOpenType(type)) 
            { 
                return OpenTypeKind.NotAnOpenType;
            } 

            OpenTypeKind openTypeKind = OpenTypeAttribute.IsOpenPropertyAvailable(type);
            if (openTypeKind == OpenTypeKind.NotAnOpenType)
            { 
                throw new InvalidOperationException(Strings.ResourceType_IncorrectOpenProperty(type));
            } 
 
            return openTypeKind;
        } 
#endif

        /// 
        /// Gets the namespace-qualified type name of the specified , 
        /// appropriate as an externally-visible type name.
        ///  
        /// Type to get name for. 
        /// The namespace-qualified type name for .
        ///  
        /// Where do type names show up?
        /// - CSDL document. Need namespace and name that are simple names.
        /// - ATOM attributes. Need namespace and name as well.
        /// 
        /// Some sample name mappings:
        /// - System.String          -> Edm.String  -- NYI, but the 'GetModel' family of methods would be correct place to add support 
        /// - System.Uri             -> System.Uri 
        /// - Custom.Client          -> Custom.Client
        /// - Custom.Client+Address  -> Custom.Client_Address 
        /// 
        private static string GetModelTypeFullName(Type type)
        {
            Debug.Assert(type != null, "type != null"); 
            string typeNamespace = WebUtil.GetModelTypeNamespace(type);
            string typeName = GetModelTypeName(type); 
            if (String.IsNullOrEmpty(typeNamespace)) 
            {
                return typeName; 
            }
            else
            {
                return typeNamespace + "." + typeName; 
            }
        } 
 
        /// 
        /// Gets the type name (without namespace) of the specified , 
        /// appropriate as an externally-visible type name.
        /// 
        /// Type to get name for.
        /// The type name for . 
        private static string GetModelTypeName(Type type)
        { 
            Debug.Assert(type != null, "type != null"); 
            if (type.IsGenericType)
            { 
                Type[] genericArguments = type.GetGenericArguments();
                StringBuilder builder = new StringBuilder(type.Name.Length * 2 * (1 + genericArguments.Length));
                if (type.IsNested)
                { 
                    Debug.Assert(type.DeclaringType != null, "type.DeclaringType != null");
                    builder.Append(GetModelTypeName(type.DeclaringType)); 
                    builder.Append('_'); 
                }
 
                builder.Append(type.Name);
                builder.Append('[');
                for (int i = 0; i < genericArguments.Length; i++)
                { 
                    if (i > 0)
                    { 
                        builder.Append(' '); 
                    }
 
                    string genericNamespace = WebUtil.GetModelTypeNamespace(genericArguments[i]);
                    if (!String.IsNullOrEmpty(genericNamespace))
                    {
                        builder.Append(genericNamespace); 
                        builder.Append('.');
                    } 
 
                    builder.Append(GetModelTypeName(genericArguments[i]));
                } 

                builder.Append(']');
                return builder.ToString();
            } 
            else if (type.IsNested)
            { 
                Debug.Assert(type.DeclaringType != null, "type.DeclaringType != null"); 
                return GetModelTypeName(type.DeclaringType) + "_" + type.Name;
            } 
            else
            {
                return type.Name;
            } 
        }
 
        ///  
        /// Sets the capacity to the actual number of elements in the List, if the list is not null and
        /// that number is less than a threshold value. 
        /// 
        /// The type of elements in the list.
        /// List to trim excess from (possibly null).
        private static void TrimExcessFromList(List list) 
        {
            if (list != null && list.Capacity > 0) 
            { 
                list.TrimExcess();
            } 
        }

        #endregion Methods.
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

                        

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