TypeUsage.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Metadata / Edm / TypeUsage.cs / 4 / TypeUsage.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
 
using System;
using System.Collections.Generic; 
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Text; 
using System.Data.Common.Utils;
using System.Linq; 
 
namespace System.Data.Metadata.Edm
{ 
    /// 
    /// Class representing a type information for an item
    /// 
    [DebuggerDisplay("EdmType={EdmType}, Facets.Count={Facets.Count}")] 
    public sealed class TypeUsage : MetadataItem
    { 
        #region Constructors 

        ///  
        /// The constructor for TypeUsage taking in a type
        /// 
        /// The type which the TypeUsage object describes
        /// Thrown if edmType argument is null 
        private TypeUsage(EdmType edmType)
        :base(MetadataFlags.Readonly) 
        { 
            EntityUtil.GenericCheckArgumentNull(edmType, "edmType");
 
            _edmType = edmType;

            // I would like to be able to assert that the edmType is ReadOnly, but
            // because some types are still in loading while the TypeUsage is being created 
            // that won't work. We should consider a way to change this
        } 
 
        /// 
        /// The constructor for TypeUsage taking in a type and a collection of facets 
        /// 
        /// The type which the TypeUsage object describes
        /// The replacement collection of facets
        /// Thrown if edmType argument is null 
        private TypeUsage(EdmType edmType, IEnumerable facets)
            : this(edmType) 
        { 
            MetadataCollection facetCollection = new MetadataCollection(facets);
            facetCollection.SetReadOnly(); 
            _facets = facetCollection.AsReadOnlyMetadataCollection();
        }
        #endregion
 
        #region Factory Methods
        ///  
        /// Factory method for creating a TypeUsage with specified EdmType 
        /// 
        /// EdmType for which to create a type usage 
        /// new TypeUsage instance with default facet values
        internal static TypeUsage Create(EdmType edmType)
        {
            return new TypeUsage(edmType); 
        }
 
        ///  
        /// Factory method for creating a TypeUsage with specified EdmType
        ///  
        /// EdmType for which to create a type usage
        /// new TypeUsage instance with default facet values
        internal static TypeUsage Create(EdmType edmType, FacetValues values)
        { 
            return new TypeUsage(edmType,
                GetDefaultFacetDescriptionsAndOverrideFacetValues(edmType, values)); 
        } 

        ///  
        /// Factory method for creating a TypeUsage with specified EdmType and facets
        /// 
        /// EdmType for which to create a type usage
        /// facets to be copied into the new TypeUsage 
        /// new TypeUsage instance
        internal static TypeUsage Create(EdmType edmType, IEnumerable facets) 
        { 
            return new TypeUsage(edmType, facets);
        } 

        internal TypeUsage ShallowCopy(FacetValues facetValues)
        {
            return TypeUsage.Create(_edmType, OverrideFacetValues(Facets, facetValues)); 
        }
 
        ///  
        /// Factory method for creating a "readonly" TypeUsage with specified EdmType
        ///  
        /// An EdmType for which to create a TypeUsage
        /// A TypeUsage instance with default facet values for the specified EdmType
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "0#edm")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")] 
        public static TypeUsage CreateDefaultTypeUsage(EdmType edmType)
        { 
            EntityUtil.CheckArgumentNull(edmType, "edmType"); 

            TypeUsage type = TypeUsage.Create(edmType); 
            return type;
        }

        ///  
        /// Factory method for creating a string TypeUsage object with the specified facets
        ///  
        /// A PrimitiveType for which to construct the TypeUsage 
        /// Whether the string type is unicode or not
        /// Whether the string type is fixed length or not 
        /// The max length of the string type
        /// A TypeUsage object describing a string type with the given facet values
        public static TypeUsage CreateStringTypeUsage(PrimitiveType primitiveType,
                                                      bool isUnicode, 
                                                      bool isFixedLength,
                                                      int maxLength) 
        { 
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType");
 
            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.String)
            {
                throw EntityUtil.NotStringTypeForTypeUsage();
            } 

            ValidateMaxLength(maxLength); 
 
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{ MaxLength = maxLength, Unicode = isUnicode, FixedLength = isFixedLength}); 

            return typeUsage;
        }
 
        /// 
        /// Factory method for creating a string TypeUsage object with the specified facets and 
        /// unbounded MaxLength 
        /// 
        /// A PrimitiveType for which to construct the TypeUsage 
        /// Whether the string type is unicode or not
        /// Whether the string type is fixed length or not
        /// A TypeUsage object describing a string type with the given facet values
        /// and unbounded MaxLength 
        public static TypeUsage CreateStringTypeUsage(PrimitiveType primitiveType,
                                                      bool isUnicode, 
                                                      bool isFixedLength) 
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.String)
            {
                throw EntityUtil.NotStringTypeForTypeUsage(); 
            }
            TypeUsage typeUsage = TypeUsage.Create(primitiveType, 
                new FacetValues{ MaxLength = TypeUsage.DefaultMaxLengthFacetValue, 
                                  Unicode = isUnicode, FixedLength = isFixedLength});
 
            return typeUsage;
        }

 
        /// 
        /// Factory method for creating a Binary TypeUsage object with the specified facets 
        ///  
        /// A PrimitiveType for which to construct TypeUsage
        /// Whether the binary type is fixed length or not 
        /// The max length of the binary type
        /// A TypeUsage object describing a binary type with the given facet values
        public static TypeUsage CreateBinaryTypeUsage(PrimitiveType primitiveType,
                                                      bool isFixedLength, 
                                                      int maxLength)
        { 
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Binary) 
            {
                throw EntityUtil.NotBinaryTypeForTypeUsage();
            }
 
            ValidateMaxLength(maxLength);
 
            TypeUsage typeUsage = TypeUsage.Create(primitiveType, 
                new FacetValues{MaxLength = maxLength, FixedLength = isFixedLength});
 
            return typeUsage;
        }

        ///  
        /// Factory method for creating a Binary TypeUsage object with the specified facets and
        /// unbounded MaxLength 
        ///  
        /// A PrimitiveType for which to construct the TypeUsage
        /// Whether the binary type is fixed length or not 
        /// A TypeUsage object describing a binary type with the given facet values
        public static TypeUsage CreateBinaryTypeUsage(PrimitiveType primitiveType, bool isFixedLength)
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Binary) 
            { 
                throw EntityUtil.NotBinaryTypeForTypeUsage();
            } 
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{MaxLength = TypeUsage.DefaultMaxLengthFacetValue,
                                 FixedLength = isFixedLength});
 
            return typeUsage;
        } 
 
        /// 
        /// Factory method for creating a DateTime TypeUsage object with the specified facets 
        /// 
        /// A PrimitiveType for which to construct the TypeUsage
        /// Precision for seconds
        /// A TypeUsage object describing a DateTime type with the given facet values 
        public static TypeUsage CreateDateTimeTypeUsage(PrimitiveType primitiveType,
                                                        byte? precision) 
        { 
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType");
 
            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.DateTime)
            {
                throw EntityUtil.NotDateTimeTypeForTypeUsage();
            } 
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{Precision = precision}); 
 
            return typeUsage;
        } 

        /// 
        /// Factory method for creating a DateTimeOffset TypeUsage object with the specified facets
        ///  
        /// A PrimitiveType for which to construct the TypeUsage
        /// Precision for seconds 
        /// A TypeUsage object describing a DateTime type with the given facet values 
        public static TypeUsage CreateDateTimeOffsetTypeUsage(PrimitiveType primitiveType,
                                                        byte? precision) 
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType");

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.DateTimeOffset) 
            {
                throw EntityUtil.NotDateTimeOffsetTypeForTypeUsage(); 
            } 

            TypeUsage typeUsage = TypeUsage.Create(primitiveType, 
                new FacetValues{ Precision = precision });

            return typeUsage;
        } 

        ///  
        /// Factory method for creating a Time TypeUsage object with the specified facets 
        /// 
        /// A PrimitiveType for which to construct the TypeUsage 
        /// Precision for seconds
        /// A TypeUsage object describing a Time type with the given facet values
        public static TypeUsage CreateTimeTypeUsage(PrimitiveType primitiveType,
                                                        byte? precision) 
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 
 
            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Time)
            { 
                throw EntityUtil.NotTimeTypeForTypeUsage();
            }
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{ Precision = precision }); 

            return typeUsage; 
        } 

 

        /// 
        /// Factory method for creating a Decimal TypeUsage object with the specified facets
        ///  
        /// A PrimitiveType for which to construct type usage
        /// The precision of the decimal type 
        /// The scale of the decimal type 
        /// A TypeUsage object describing a decimal type with the given facet values
        public static TypeUsage CreateDecimalTypeUsage(PrimitiveType primitiveType, 
                                                       byte precision,
                                                       byte scale)
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Decimal) 
            { 
                throw EntityUtil.NotDecimalTypeForTypeUsage();
            } 

            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{Precision = precision, Scale = scale });
 
            return typeUsage;
        } 
 
        /// 
        /// Factory method for creating a Decimal TypeUsage object with unbounded precision and scale 
        /// 
        /// The PrimitiveType for which to construct type usage
        /// A TypeUsage object describing a decimal type with unbounded precision and scale
        public static TypeUsage CreateDecimalTypeUsage(PrimitiveType primitiveType) 
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 
 
            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Decimal)
            { 
                throw EntityUtil.NotDecimalTypeForTypeUsage();
            }
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{ Precision = TypeUsage.DefaultPrecisionFacetValue, Scale = TypeUsage.DefaultScaleFacetValue }); 

            return typeUsage; 
        } 
        #endregion
 
        #region Fields
        private TypeUsage _modelTypeUsage;
        private readonly EdmType _edmType;
        private ReadOnlyMetadataCollection _facets; 
        private string _identity;
 
        ///  
        /// Set of facets that should be included in identity for TypeUsage
        ///  
        /// keep this sorted for binary searching
        private static readonly string[] s_identityFacets = new string[] {
            DbProviderManifest.DefaultValueFacetName,
            DbProviderManifest.FixedLengthFacetName, 
            DbProviderManifest.MaxLengthFacetName,
            DbProviderManifest.NullableFacetName, 
            DbProviderManifest.PrecisionFacetName, 
            DbProviderManifest.ScaleFacetName,
            DbProviderManifest.UnicodeFacetName, 
        };

        internal static readonly EdmConstants.Unbounded DefaultMaxLengthFacetValue       = EdmConstants.UnboundedValue;
        internal static readonly EdmConstants.Unbounded DefaultPrecisionFacetValue       = EdmConstants.UnboundedValue; 
        internal static readonly EdmConstants.Unbounded DefaultScaleFacetValue           = EdmConstants.UnboundedValue;
        internal static readonly bool                   DefaultUnicodeFacetValue         = true; 
        internal static readonly bool                   DefaultFixedLengthFacetValue     = false; 
        internal static readonly byte?                   DefaultDateTimePrecisionFacetValue = null;
 
        #endregion

        #region Properties
        ///  
        /// Returns the kind of the type
        ///  
        public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.TypeUsage; } } 

        ///  
        /// Gets the type that this TypeUsage describes
        /// 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
        [MetadataProperty(BuiltInTypeKind.EdmType, false)] 
        public EdmType EdmType
        { 
            get 
            {
                return _edmType; 
            }
        }

        ///  
        /// Gets the list of facets for the type in this TypeUsage
        ///  
        [MetadataProperty(BuiltInTypeKind.Facet, true)] 
        public ReadOnlyMetadataCollection Facets
        { 
            get
            {
                if (null == _facets)
                { 
                    MetadataCollection facets = new MetadataCollection(GetFacets());
                    // we never modify the collection so we can set it readonly from the start 
                    facets.SetReadOnly(); 
                    System.Threading.Interlocked.CompareExchange(ref _facets, facets.AsReadOnlyMetadataCollection(), null);
                } 
                return _facets;
            }
        }
        #endregion 

        #region Methods 
        ///  
        /// Returns a Model type usage for a provider type
        ///  
        /// model (CSpace) type usage
        internal TypeUsage GetModelTypeUsage()
        {
            if (_modelTypeUsage == null) 
            {
                EdmType edmType = this.EdmType; 
 
                // If the edm type is already a cspace type, return the same type
                if (edmType.DataSpace == DataSpace.CSpace || edmType.DataSpace == DataSpace.OSpace) 
                {
                    return this;
                }
 
                TypeUsage result;
                if (Helper.IsRowType(edmType)) 
                { 
                    RowType sspaceRowType = (RowType)edmType;
                    EdmProperty[] properties = new EdmProperty[sspaceRowType.Properties.Count]; 
                    for (int i = 0; i < properties.Length; i++)
                    {
                        EdmProperty sspaceProperty = sspaceRowType.Properties[i];
                        TypeUsage newTypeUsage = sspaceProperty.TypeUsage.GetModelTypeUsage(); 
                        properties[i] = new EdmProperty(sspaceProperty.Name, newTypeUsage);
                    } 
                    RowType edmRowType = new RowType(properties, sspaceRowType.InitializerMetadata); 
                    result = TypeUsage.Create(edmRowType, this.Facets);
                } 
                else if (Helper.IsCollectionType(edmType))
                {
                    CollectionType sspaceCollectionType = ((CollectionType)edmType);
                    TypeUsage newTypeUsage = sspaceCollectionType.TypeUsage.GetModelTypeUsage(); 
                    result = TypeUsage.Create(new CollectionType(newTypeUsage), this.Facets);
                } 
                else if (Helper.IsRefType(edmType)) 
                {
                    System.Diagnostics.Debug.Assert(((RefType)edmType).ElementType.DataSpace == DataSpace.CSpace); 
                    result = this;
                }
                else if (Helper.IsPrimitiveType(edmType))
                { 
                    result = ((PrimitiveType)edmType).ProviderManifest.GetEdmType(this);
 
                    if (result == null) 
                    {
                        throw EntityUtil.ProviderIncompatible(System.Data.Entity.Strings.Mapping_ProviderReturnsNullType(this.ToString())); 
                    }

                    if (!TypeSemantics.IsNullable(this))
                    { 
                        result = TypeUsage.Create(result.EdmType,
                            OverrideFacetValues(result.Facets, 
                                new FacetValues{ Nullable = false })); 
                    }
                } 
                else if (Helper.IsEntityTypeBase(edmType) || Helper.IsComplexType(edmType))
                {
                    result = this;
                } 
                else
                { 
                    System.Diagnostics.Debug.Assert(false, "Unexpected type found in entity data reader"); 
                    return null;
                } 
                System.Threading.Interlocked.CompareExchange(ref _modelTypeUsage, result, null);
            }
            return _modelTypeUsage;
        } 

        ///  
        /// check if "this" is a subtype of the specified TypeUsage 
        /// 
        /// The typeUsage to be checked 
        /// true if this typeUsage is a subtype of the specified typeUsage
        public bool IsSubtypeOf(TypeUsage typeUsage)
        {
            if (EdmType == null || typeUsage == null) 
            {
                return false; 
            } 

            return EdmType.IsSubtypeOf(typeUsage.EdmType); 
        }

        private IEnumerable GetFacets()
        { 
            foreach (FacetDescription facetDescription in _edmType.GetAssociatedFacetDescriptions())
            { 
                yield return facetDescription.DefaultValueFacet; 
            }
        } 

        internal override void SetReadOnly()
        {
            Debug.Fail("TypeUsage.SetReadOnly should not need to ever be called"); 
            base.SetReadOnly();
        } 
 
        /// 
        /// returns the identity of the type usage 
        /// 
        internal override String Identity
        {
            get 
            {
                if (this.Facets.Count == 0) 
                { 
                    return this.EdmType.Identity;
                } 

                if (this._identity == null)
                {
                    StringBuilder builder = new StringBuilder(128); 
                    BuildIdentity(builder);
                    string identity = builder.ToString(); 
                    System.Threading.Interlocked.CompareExchange(ref _identity, identity, null); 
                }
                return this._identity; 
            }
        }

        private static IEnumerable GetDefaultFacetDescriptionsAndOverrideFacetValues(EdmType type, FacetValues values) 
        {
            return OverrideFacetValues(type.GetAssociatedFacetDescriptions(), 
                fd => fd, 
                fd => fd.DefaultValueFacet,
                values); 
        }


        private static IEnumerable OverrideFacetValues(IEnumerable facets, FacetValues values) 
        {
            return OverrideFacetValues(facets, 
                f => f.Description, 
                f => f,
                values); 
        }


        private static IEnumerable OverrideFacetValues(IEnumerable facetThings, 
                Func getDescription,
                Func getFacet, 
                FacetValues values) 
        {
            // yield all the non custom values 
            foreach (var thing in facetThings)
            {
                FacetDescription description = getDescription(thing);
                Facet facet; 
                if (!description.IsConstant && values.TryGetFacet(description, out facet))
                { 
                    yield return facet; 
                }
                else 
                {
                    yield return getFacet(thing);
                }
            } 

        } 
 
        internal override void BuildIdentity(StringBuilder builder)
        { 
            // if we've already cached the identity, simply append it
            if (null != _identity)
            {
                builder.Append(_identity); 
                return;
            } 
 
            builder.Append(this.EdmType.Identity);
 
            builder.Append("(");
            bool first = true;
            for (int j = 0; j < this.Facets.Count; j++)
            { 
                Facet facet = this.Facets[j];
 
                if (0 <= Array.BinarySearch(s_identityFacets, facet.Name, StringComparer.Ordinal)) 
                {
                    if (first) { first = false; } 
                    else { builder.Append(","); }

                    builder.Append(facet.Name);
                    builder.Append("="); 
                    // If the facet is present, add its value to the identity
                    // We only include built-in system facets for the identity 
                    builder.Append(facet.Value ?? String.Empty); 
                }
            } 
            builder.Append(")");
        }

        ///  
        /// 
        public override string ToString() 
        { 
            return EdmType.ToString();
        } 

        /// 
        /// EdmEquals override verifying the equivalence of all facets. Two facets are considered
        /// equal if they have the same name and the same value (Object.Equals) 
        /// 
        ///  
        ///  
        internal override bool EdmEquals(MetadataItem item)
        { 
            // short-circuit if this and other are reference equivalent
            if (Object.ReferenceEquals(this, item)) { return true; }

            // check type of item 
            if (null == item || BuiltInTypeKind.TypeUsage != item.BuiltInTypeKind) { return false; }
            TypeUsage other = (TypeUsage)item; 
 
            // verify edm types are equivalent
            if (!this.EdmType.EdmEquals(other.EdmType)) { return false; } 

            // if both usages have default facets, no need to compare
            if (null == this._facets && null == other._facets) { return true; }
 
            // initialize facets and compare
            if (this.Facets.Count != other.Facets.Count) { return false; } 
 
            foreach (Facet thisFacet in this.Facets)
            { 
                Facet otherFacet;
                if (!other.Facets.TryGetValue(thisFacet.Name, false, out otherFacet))
                {
                    // other type usage doesn't have the same facets as this type usage 
                    return false;
                } 
 
                // check that the facet values are the same
                if (!Object.Equals(thisFacet.Value, otherFacet.Value)) 
                {
                    return false;
                }
            } 

            return true; 
        } 

        private static void ValidateMaxLength(int maxLength) 
        {
            if (maxLength <= 0)
            {
                throw EntityUtil.ArgumentOutOfRange(System.Data.Entity.Strings.InvalidMaxLengthSize, "maxLength"); 
            }
        } 
 
        #endregion
 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
 
using System;
using System.Collections.Generic; 
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Text; 
using System.Data.Common.Utils;
using System.Linq; 
 
namespace System.Data.Metadata.Edm
{ 
    /// 
    /// Class representing a type information for an item
    /// 
    [DebuggerDisplay("EdmType={EdmType}, Facets.Count={Facets.Count}")] 
    public sealed class TypeUsage : MetadataItem
    { 
        #region Constructors 

        ///  
        /// The constructor for TypeUsage taking in a type
        /// 
        /// The type which the TypeUsage object describes
        /// Thrown if edmType argument is null 
        private TypeUsage(EdmType edmType)
        :base(MetadataFlags.Readonly) 
        { 
            EntityUtil.GenericCheckArgumentNull(edmType, "edmType");
 
            _edmType = edmType;

            // I would like to be able to assert that the edmType is ReadOnly, but
            // because some types are still in loading while the TypeUsage is being created 
            // that won't work. We should consider a way to change this
        } 
 
        /// 
        /// The constructor for TypeUsage taking in a type and a collection of facets 
        /// 
        /// The type which the TypeUsage object describes
        /// The replacement collection of facets
        /// Thrown if edmType argument is null 
        private TypeUsage(EdmType edmType, IEnumerable facets)
            : this(edmType) 
        { 
            MetadataCollection facetCollection = new MetadataCollection(facets);
            facetCollection.SetReadOnly(); 
            _facets = facetCollection.AsReadOnlyMetadataCollection();
        }
        #endregion
 
        #region Factory Methods
        ///  
        /// Factory method for creating a TypeUsage with specified EdmType 
        /// 
        /// EdmType for which to create a type usage 
        /// new TypeUsage instance with default facet values
        internal static TypeUsage Create(EdmType edmType)
        {
            return new TypeUsage(edmType); 
        }
 
        ///  
        /// Factory method for creating a TypeUsage with specified EdmType
        ///  
        /// EdmType for which to create a type usage
        /// new TypeUsage instance with default facet values
        internal static TypeUsage Create(EdmType edmType, FacetValues values)
        { 
            return new TypeUsage(edmType,
                GetDefaultFacetDescriptionsAndOverrideFacetValues(edmType, values)); 
        } 

        ///  
        /// Factory method for creating a TypeUsage with specified EdmType and facets
        /// 
        /// EdmType for which to create a type usage
        /// facets to be copied into the new TypeUsage 
        /// new TypeUsage instance
        internal static TypeUsage Create(EdmType edmType, IEnumerable facets) 
        { 
            return new TypeUsage(edmType, facets);
        } 

        internal TypeUsage ShallowCopy(FacetValues facetValues)
        {
            return TypeUsage.Create(_edmType, OverrideFacetValues(Facets, facetValues)); 
        }
 
        ///  
        /// Factory method for creating a "readonly" TypeUsage with specified EdmType
        ///  
        /// An EdmType for which to create a TypeUsage
        /// A TypeUsage instance with default facet values for the specified EdmType
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "0#edm")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "edm")] 
        public static TypeUsage CreateDefaultTypeUsage(EdmType edmType)
        { 
            EntityUtil.CheckArgumentNull(edmType, "edmType"); 

            TypeUsage type = TypeUsage.Create(edmType); 
            return type;
        }

        ///  
        /// Factory method for creating a string TypeUsage object with the specified facets
        ///  
        /// A PrimitiveType for which to construct the TypeUsage 
        /// Whether the string type is unicode or not
        /// Whether the string type is fixed length or not 
        /// The max length of the string type
        /// A TypeUsage object describing a string type with the given facet values
        public static TypeUsage CreateStringTypeUsage(PrimitiveType primitiveType,
                                                      bool isUnicode, 
                                                      bool isFixedLength,
                                                      int maxLength) 
        { 
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType");
 
            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.String)
            {
                throw EntityUtil.NotStringTypeForTypeUsage();
            } 

            ValidateMaxLength(maxLength); 
 
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{ MaxLength = maxLength, Unicode = isUnicode, FixedLength = isFixedLength}); 

            return typeUsage;
        }
 
        /// 
        /// Factory method for creating a string TypeUsage object with the specified facets and 
        /// unbounded MaxLength 
        /// 
        /// A PrimitiveType for which to construct the TypeUsage 
        /// Whether the string type is unicode or not
        /// Whether the string type is fixed length or not
        /// A TypeUsage object describing a string type with the given facet values
        /// and unbounded MaxLength 
        public static TypeUsage CreateStringTypeUsage(PrimitiveType primitiveType,
                                                      bool isUnicode, 
                                                      bool isFixedLength) 
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.String)
            {
                throw EntityUtil.NotStringTypeForTypeUsage(); 
            }
            TypeUsage typeUsage = TypeUsage.Create(primitiveType, 
                new FacetValues{ MaxLength = TypeUsage.DefaultMaxLengthFacetValue, 
                                  Unicode = isUnicode, FixedLength = isFixedLength});
 
            return typeUsage;
        }

 
        /// 
        /// Factory method for creating a Binary TypeUsage object with the specified facets 
        ///  
        /// A PrimitiveType for which to construct TypeUsage
        /// Whether the binary type is fixed length or not 
        /// The max length of the binary type
        /// A TypeUsage object describing a binary type with the given facet values
        public static TypeUsage CreateBinaryTypeUsage(PrimitiveType primitiveType,
                                                      bool isFixedLength, 
                                                      int maxLength)
        { 
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Binary) 
            {
                throw EntityUtil.NotBinaryTypeForTypeUsage();
            }
 
            ValidateMaxLength(maxLength);
 
            TypeUsage typeUsage = TypeUsage.Create(primitiveType, 
                new FacetValues{MaxLength = maxLength, FixedLength = isFixedLength});
 
            return typeUsage;
        }

        ///  
        /// Factory method for creating a Binary TypeUsage object with the specified facets and
        /// unbounded MaxLength 
        ///  
        /// A PrimitiveType for which to construct the TypeUsage
        /// Whether the binary type is fixed length or not 
        /// A TypeUsage object describing a binary type with the given facet values
        public static TypeUsage CreateBinaryTypeUsage(PrimitiveType primitiveType, bool isFixedLength)
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Binary) 
            { 
                throw EntityUtil.NotBinaryTypeForTypeUsage();
            } 
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{MaxLength = TypeUsage.DefaultMaxLengthFacetValue,
                                 FixedLength = isFixedLength});
 
            return typeUsage;
        } 
 
        /// 
        /// Factory method for creating a DateTime TypeUsage object with the specified facets 
        /// 
        /// A PrimitiveType for which to construct the TypeUsage
        /// Precision for seconds
        /// A TypeUsage object describing a DateTime type with the given facet values 
        public static TypeUsage CreateDateTimeTypeUsage(PrimitiveType primitiveType,
                                                        byte? precision) 
        { 
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType");
 
            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.DateTime)
            {
                throw EntityUtil.NotDateTimeTypeForTypeUsage();
            } 
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{Precision = precision}); 
 
            return typeUsage;
        } 

        /// 
        /// Factory method for creating a DateTimeOffset TypeUsage object with the specified facets
        ///  
        /// A PrimitiveType for which to construct the TypeUsage
        /// Precision for seconds 
        /// A TypeUsage object describing a DateTime type with the given facet values 
        public static TypeUsage CreateDateTimeOffsetTypeUsage(PrimitiveType primitiveType,
                                                        byte? precision) 
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType");

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.DateTimeOffset) 
            {
                throw EntityUtil.NotDateTimeOffsetTypeForTypeUsage(); 
            } 

            TypeUsage typeUsage = TypeUsage.Create(primitiveType, 
                new FacetValues{ Precision = precision });

            return typeUsage;
        } 

        ///  
        /// Factory method for creating a Time TypeUsage object with the specified facets 
        /// 
        /// A PrimitiveType for which to construct the TypeUsage 
        /// Precision for seconds
        /// A TypeUsage object describing a Time type with the given facet values
        public static TypeUsage CreateTimeTypeUsage(PrimitiveType primitiveType,
                                                        byte? precision) 
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 
 
            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Time)
            { 
                throw EntityUtil.NotTimeTypeForTypeUsage();
            }
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{ Precision = precision }); 

            return typeUsage; 
        } 

 

        /// 
        /// Factory method for creating a Decimal TypeUsage object with the specified facets
        ///  
        /// A PrimitiveType for which to construct type usage
        /// The precision of the decimal type 
        /// The scale of the decimal type 
        /// A TypeUsage object describing a decimal type with the given facet values
        public static TypeUsage CreateDecimalTypeUsage(PrimitiveType primitiveType, 
                                                       byte precision,
                                                       byte scale)
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 

            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Decimal) 
            { 
                throw EntityUtil.NotDecimalTypeForTypeUsage();
            } 

            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{Precision = precision, Scale = scale });
 
            return typeUsage;
        } 
 
        /// 
        /// Factory method for creating a Decimal TypeUsage object with unbounded precision and scale 
        /// 
        /// The PrimitiveType for which to construct type usage
        /// A TypeUsage object describing a decimal type with unbounded precision and scale
        public static TypeUsage CreateDecimalTypeUsage(PrimitiveType primitiveType) 
        {
            EntityUtil.CheckArgumentNull(primitiveType, "primitiveType"); 
 
            if (primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Decimal)
            { 
                throw EntityUtil.NotDecimalTypeForTypeUsage();
            }
            TypeUsage typeUsage = TypeUsage.Create(primitiveType,
                new FacetValues{ Precision = TypeUsage.DefaultPrecisionFacetValue, Scale = TypeUsage.DefaultScaleFacetValue }); 

            return typeUsage; 
        } 
        #endregion
 
        #region Fields
        private TypeUsage _modelTypeUsage;
        private readonly EdmType _edmType;
        private ReadOnlyMetadataCollection _facets; 
        private string _identity;
 
        ///  
        /// Set of facets that should be included in identity for TypeUsage
        ///  
        /// keep this sorted for binary searching
        private static readonly string[] s_identityFacets = new string[] {
            DbProviderManifest.DefaultValueFacetName,
            DbProviderManifest.FixedLengthFacetName, 
            DbProviderManifest.MaxLengthFacetName,
            DbProviderManifest.NullableFacetName, 
            DbProviderManifest.PrecisionFacetName, 
            DbProviderManifest.ScaleFacetName,
            DbProviderManifest.UnicodeFacetName, 
        };

        internal static readonly EdmConstants.Unbounded DefaultMaxLengthFacetValue       = EdmConstants.UnboundedValue;
        internal static readonly EdmConstants.Unbounded DefaultPrecisionFacetValue       = EdmConstants.UnboundedValue; 
        internal static readonly EdmConstants.Unbounded DefaultScaleFacetValue           = EdmConstants.UnboundedValue;
        internal static readonly bool                   DefaultUnicodeFacetValue         = true; 
        internal static readonly bool                   DefaultFixedLengthFacetValue     = false; 
        internal static readonly byte?                   DefaultDateTimePrecisionFacetValue = null;
 
        #endregion

        #region Properties
        ///  
        /// Returns the kind of the type
        ///  
        public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.TypeUsage; } } 

        ///  
        /// Gets the type that this TypeUsage describes
        /// 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
        [MetadataProperty(BuiltInTypeKind.EdmType, false)] 
        public EdmType EdmType
        { 
            get 
            {
                return _edmType; 
            }
        }

        ///  
        /// Gets the list of facets for the type in this TypeUsage
        ///  
        [MetadataProperty(BuiltInTypeKind.Facet, true)] 
        public ReadOnlyMetadataCollection Facets
        { 
            get
            {
                if (null == _facets)
                { 
                    MetadataCollection facets = new MetadataCollection(GetFacets());
                    // we never modify the collection so we can set it readonly from the start 
                    facets.SetReadOnly(); 
                    System.Threading.Interlocked.CompareExchange(ref _facets, facets.AsReadOnlyMetadataCollection(), null);
                } 
                return _facets;
            }
        }
        #endregion 

        #region Methods 
        ///  
        /// Returns a Model type usage for a provider type
        ///  
        /// model (CSpace) type usage
        internal TypeUsage GetModelTypeUsage()
        {
            if (_modelTypeUsage == null) 
            {
                EdmType edmType = this.EdmType; 
 
                // If the edm type is already a cspace type, return the same type
                if (edmType.DataSpace == DataSpace.CSpace || edmType.DataSpace == DataSpace.OSpace) 
                {
                    return this;
                }
 
                TypeUsage result;
                if (Helper.IsRowType(edmType)) 
                { 
                    RowType sspaceRowType = (RowType)edmType;
                    EdmProperty[] properties = new EdmProperty[sspaceRowType.Properties.Count]; 
                    for (int i = 0; i < properties.Length; i++)
                    {
                        EdmProperty sspaceProperty = sspaceRowType.Properties[i];
                        TypeUsage newTypeUsage = sspaceProperty.TypeUsage.GetModelTypeUsage(); 
                        properties[i] = new EdmProperty(sspaceProperty.Name, newTypeUsage);
                    } 
                    RowType edmRowType = new RowType(properties, sspaceRowType.InitializerMetadata); 
                    result = TypeUsage.Create(edmRowType, this.Facets);
                } 
                else if (Helper.IsCollectionType(edmType))
                {
                    CollectionType sspaceCollectionType = ((CollectionType)edmType);
                    TypeUsage newTypeUsage = sspaceCollectionType.TypeUsage.GetModelTypeUsage(); 
                    result = TypeUsage.Create(new CollectionType(newTypeUsage), this.Facets);
                } 
                else if (Helper.IsRefType(edmType)) 
                {
                    System.Diagnostics.Debug.Assert(((RefType)edmType).ElementType.DataSpace == DataSpace.CSpace); 
                    result = this;
                }
                else if (Helper.IsPrimitiveType(edmType))
                { 
                    result = ((PrimitiveType)edmType).ProviderManifest.GetEdmType(this);
 
                    if (result == null) 
                    {
                        throw EntityUtil.ProviderIncompatible(System.Data.Entity.Strings.Mapping_ProviderReturnsNullType(this.ToString())); 
                    }

                    if (!TypeSemantics.IsNullable(this))
                    { 
                        result = TypeUsage.Create(result.EdmType,
                            OverrideFacetValues(result.Facets, 
                                new FacetValues{ Nullable = false })); 
                    }
                } 
                else if (Helper.IsEntityTypeBase(edmType) || Helper.IsComplexType(edmType))
                {
                    result = this;
                } 
                else
                { 
                    System.Diagnostics.Debug.Assert(false, "Unexpected type found in entity data reader"); 
                    return null;
                } 
                System.Threading.Interlocked.CompareExchange(ref _modelTypeUsage, result, null);
            }
            return _modelTypeUsage;
        } 

        ///  
        /// check if "this" is a subtype of the specified TypeUsage 
        /// 
        /// The typeUsage to be checked 
        /// true if this typeUsage is a subtype of the specified typeUsage
        public bool IsSubtypeOf(TypeUsage typeUsage)
        {
            if (EdmType == null || typeUsage == null) 
            {
                return false; 
            } 

            return EdmType.IsSubtypeOf(typeUsage.EdmType); 
        }

        private IEnumerable GetFacets()
        { 
            foreach (FacetDescription facetDescription in _edmType.GetAssociatedFacetDescriptions())
            { 
                yield return facetDescription.DefaultValueFacet; 
            }
        } 

        internal override void SetReadOnly()
        {
            Debug.Fail("TypeUsage.SetReadOnly should not need to ever be called"); 
            base.SetReadOnly();
        } 
 
        /// 
        /// returns the identity of the type usage 
        /// 
        internal override String Identity
        {
            get 
            {
                if (this.Facets.Count == 0) 
                { 
                    return this.EdmType.Identity;
                } 

                if (this._identity == null)
                {
                    StringBuilder builder = new StringBuilder(128); 
                    BuildIdentity(builder);
                    string identity = builder.ToString(); 
                    System.Threading.Interlocked.CompareExchange(ref _identity, identity, null); 
                }
                return this._identity; 
            }
        }

        private static IEnumerable GetDefaultFacetDescriptionsAndOverrideFacetValues(EdmType type, FacetValues values) 
        {
            return OverrideFacetValues(type.GetAssociatedFacetDescriptions(), 
                fd => fd, 
                fd => fd.DefaultValueFacet,
                values); 
        }


        private static IEnumerable OverrideFacetValues(IEnumerable facets, FacetValues values) 
        {
            return OverrideFacetValues(facets, 
                f => f.Description, 
                f => f,
                values); 
        }


        private static IEnumerable OverrideFacetValues(IEnumerable facetThings, 
                Func getDescription,
                Func getFacet, 
                FacetValues values) 
        {
            // yield all the non custom values 
            foreach (var thing in facetThings)
            {
                FacetDescription description = getDescription(thing);
                Facet facet; 
                if (!description.IsConstant && values.TryGetFacet(description, out facet))
                { 
                    yield return facet; 
                }
                else 
                {
                    yield return getFacet(thing);
                }
            } 

        } 
 
        internal override void BuildIdentity(StringBuilder builder)
        { 
            // if we've already cached the identity, simply append it
            if (null != _identity)
            {
                builder.Append(_identity); 
                return;
            } 
 
            builder.Append(this.EdmType.Identity);
 
            builder.Append("(");
            bool first = true;
            for (int j = 0; j < this.Facets.Count; j++)
            { 
                Facet facet = this.Facets[j];
 
                if (0 <= Array.BinarySearch(s_identityFacets, facet.Name, StringComparer.Ordinal)) 
                {
                    if (first) { first = false; } 
                    else { builder.Append(","); }

                    builder.Append(facet.Name);
                    builder.Append("="); 
                    // If the facet is present, add its value to the identity
                    // We only include built-in system facets for the identity 
                    builder.Append(facet.Value ?? String.Empty); 
                }
            } 
            builder.Append(")");
        }

        ///  
        /// 
        public override string ToString() 
        { 
            return EdmType.ToString();
        } 

        /// 
        /// EdmEquals override verifying the equivalence of all facets. Two facets are considered
        /// equal if they have the same name and the same value (Object.Equals) 
        /// 
        ///  
        ///  
        internal override bool EdmEquals(MetadataItem item)
        { 
            // short-circuit if this and other are reference equivalent
            if (Object.ReferenceEquals(this, item)) { return true; }

            // check type of item 
            if (null == item || BuiltInTypeKind.TypeUsage != item.BuiltInTypeKind) { return false; }
            TypeUsage other = (TypeUsage)item; 
 
            // verify edm types are equivalent
            if (!this.EdmType.EdmEquals(other.EdmType)) { return false; } 

            // if both usages have default facets, no need to compare
            if (null == this._facets && null == other._facets) { return true; }
 
            // initialize facets and compare
            if (this.Facets.Count != other.Facets.Count) { return false; } 
 
            foreach (Facet thisFacet in this.Facets)
            { 
                Facet otherFacet;
                if (!other.Facets.TryGetValue(thisFacet.Name, false, out otherFacet))
                {
                    // other type usage doesn't have the same facets as this type usage 
                    return false;
                } 
 
                // check that the facet values are the same
                if (!Object.Equals(thisFacet.Value, otherFacet.Value)) 
                {
                    return false;
                }
            } 

            return true; 
        } 

        private static void ValidateMaxLength(int maxLength) 
        {
            if (maxLength <= 0)
            {
                throw EntityUtil.ArgumentOutOfRange(System.Data.Entity.Strings.InvalidMaxLengthSize, "maxLength"); 
            }
        } 
 
        #endregion
 
    }
}

// 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