//--------------------------------------------------------------------- // <copyright file="Facet.cs" company="Microsoft"> // Copyright (c) Microsoft Corporation. All rights reserved. // </copyright> // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- namespace System.Data.Metadata.Edm { using System; using System.Diagnostics; using System.Globalization; /// <summary> /// Class for representing a Facet object /// This object is Immutable (not just set to readonly) and /// some parts of the system are depending on that behavior /// </summary> [DebuggerDisplay("{Name,nq}={Value}")] public sealed class Facet : MetadataItem { #region Constructors /// <summary> /// The constructor for constructing a Facet object with the facet description and a value /// </summary> /// <param name="facetDescription">The object describing this facet</param> /// <param name="value">The value of the facet</param> /// <exception cref="System.ArgumentNullException">Thrown if facetDescription argument is null</exception> private Facet(FacetDescription facetDescription, object value) :base(MetadataFlags.Readonly) { EntityUtil.GenericCheckArgumentNull(facetDescription, "facetDescription"); _facetDescription = facetDescription; _value = value; } /// <summary> /// Creates a Facet instance with the specified value for the given /// facet description. /// </summary> /// <param name="facetDescription">The object describing this facet</param> /// <param name="value">The value of the facet</param> /// <exception cref="System.ArgumentNullException">Thrown if facetDescription argument is null</exception> internal static Facet Create(FacetDescription facetDescription, object value) { return Create(facetDescription, value, false); } /// <summary> /// Creates a Facet instance with the specified value for the given /// facet description. /// </summary> /// <param name="facetDescription">The object describing this facet</param> /// <param name="value">The value of the facet</param> /// <param name="bypassKnownValues">true to bypass caching and known values; false otherwise.</param> /// <exception cref="System.ArgumentNullException">Thrown if facetDescription argument is null</exception> internal static Facet Create(FacetDescription facetDescription, object value, bool bypassKnownValues) { EntityUtil.CheckArgumentNull(facetDescription, "facetDescription"); if (!bypassKnownValues) { // Reuse facets with a null value. if (object.ReferenceEquals(value, null)) { return facetDescription.NullValueFacet; } // Reuse facets with a default value. if (object.Equals(facetDescription.DefaultValue, value)) { return facetDescription.DefaultValueFacet; } // Special case boolean facets. if (facetDescription.FacetType.Identity == "Edm.Boolean") { bool boolValue = (bool)value; return facetDescription.GetBooleanFacet(boolValue); } } Facet result = new Facet(facetDescription, value); // Check the type of the value only if we know what the correct CLR type is if (value != null && !Helper.IsUnboundedFacetValue(result) && !Helper.IsVariableFacetValue(result) && result.FacetType.ClrType != null) { Type valueType = value.GetType(); Debug.Assert( valueType == result.FacetType.ClrType || result.FacetType.ClrType.IsAssignableFrom(valueType), string.Format(CultureInfo.CurrentCulture, "The facet {0} has type {1}, but a value of type {2} was supplied.", result.Name, result.FacetType.ClrType, valueType) ); } return result; } #endregion #region Fields /// <summary>The object describing this facet.</summary> private readonly FacetDescription _facetDescription; /// <summary>The value assigned to this facet.</summary> private readonly object _value; #endregion #region Properties /// <summary> /// Returns the kind of the type /// </summary> public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.Facet; } } /// <summary> /// Gets the description object for describing the facet /// </summary> public FacetDescription Description { get { return _facetDescription; } } /// <summary> /// Gets/Sets the name of the facet /// </summary> [MetadataProperty(PrimitiveTypeKind.String, false)] public String Name { get { return _facetDescription.FacetName; } } /// <summary> /// Gets/Sets the type of the facet /// </summary> [MetadataProperty(BuiltInTypeKind.EdmType, false)] public EdmType FacetType { get { return _facetDescription.FacetType; } } /// <summary> /// Gets/Sets the value of the facet /// </summary> /// <exception cref="System.InvalidOperationException">Thrown if the Facet instance is in ReadOnly state</exception> [MetadataProperty(typeof(Object), false)] public Object Value { get { return _value; } } /// <summary> /// Gets the identity for this item as a string /// </summary> internal override string Identity { get { return _facetDescription.FacetName; } } /// <summary> /// Indicates whether the value of the facet is unbounded /// </summary> public bool IsUnbounded { get { return object.ReferenceEquals(Value, EdmConstants.UnboundedValue); } } #endregion #region Methods /// <summary> /// Overriding System.Object.ToString to provide better String representation /// for this type. /// </summary> public override string ToString() { return this.Name; } #endregion } }