Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataWeb / Server / System / Data / Services / Providers / ResourceType.cs / 2 / 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.