274 lines
13 KiB
C#
274 lines
13 KiB
C#
//---------------------------------------------------------------------
|
|
// <copyright file="ClrProviderManifest.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//
|
|
// @owner [....]
|
|
// @backupOwner [....]
|
|
//---------------------------------------------------------------------
|
|
|
|
using System.Collections.Generic;
|
|
using System.Data.Common;
|
|
using System.Diagnostics;
|
|
using System.Collections.ObjectModel;
|
|
using System.Data.Spatial;
|
|
using System.Threading;
|
|
using System.Linq;
|
|
|
|
namespace System.Data.Metadata.Edm
|
|
{
|
|
internal class ClrProviderManifest : DbProviderManifest
|
|
{
|
|
private const int s_PrimitiveTypeCount = 17;
|
|
private System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType> _primitiveTypes;
|
|
private static ClrProviderManifest _instance = new ClrProviderManifest();
|
|
|
|
/// <summary>
|
|
/// A private constructor to prevent other places from instantiating this class
|
|
/// </summary>
|
|
private ClrProviderManifest()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the EDM provider manifest singleton instance
|
|
/// </summary>
|
|
internal static ClrProviderManifest Instance
|
|
{
|
|
get
|
|
{
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the namespace used by this provider manifest
|
|
/// </summary>
|
|
public override string NamespaceName
|
|
{
|
|
get { return EdmConstants.ClrPrimitiveTypeNamespace; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the primitive type corresponding to the given CLR type
|
|
/// </summary>
|
|
/// <param name="clrType">The CLR type for which the PrimitiveType object is retrieved</param>
|
|
/// <param name="primitiveType">The retrieved primitive type</param>
|
|
/// <returns>True if a primitive type is returned</returns>
|
|
internal bool TryGetPrimitiveType(Type clrType, out PrimitiveType primitiveType)
|
|
{
|
|
primitiveType = null;
|
|
PrimitiveTypeKind resolvedTypeKind;
|
|
if (TryGetPrimitiveTypeKind(clrType, out resolvedTypeKind))
|
|
{
|
|
InitializePrimitiveTypes();
|
|
primitiveType = _primitiveTypes[(int)resolvedTypeKind];
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the <see cref="PrimitiveTypeKind"/> corresponding to the given CLR type
|
|
/// </summary>
|
|
/// <param name="clrType">The CLR type for which the PrimitiveTypeKind value should be resolved</param>
|
|
/// <param name="primitiveType">The PrimitiveTypeKind value to which the CLR type resolves, if any.</param>
|
|
/// <returns>True if the CLR type represents a primitive (EDM) type; otherwise false.</returns>
|
|
internal bool TryGetPrimitiveTypeKind(Type clrType, out PrimitiveTypeKind resolvedPrimitiveTypeKind)
|
|
{
|
|
PrimitiveTypeKind? primitiveTypeKind = null;
|
|
if (!clrType.IsEnum) // Enums return the TypeCode of their underlying type
|
|
{
|
|
// As an optimization, short-circuit when the provided type has a known type code.
|
|
switch (Type.GetTypeCode(clrType))
|
|
{
|
|
// PrimitiveTypeKind.Binary = byte[] = TypeCode.Object
|
|
case TypeCode.Boolean:
|
|
primitiveTypeKind = PrimitiveTypeKind.Boolean;
|
|
break;
|
|
case TypeCode.Byte:
|
|
primitiveTypeKind = PrimitiveTypeKind.Byte;
|
|
break;
|
|
case TypeCode.DateTime:
|
|
primitiveTypeKind = PrimitiveTypeKind.DateTime;
|
|
break;
|
|
// PrimitiveTypeKind.DateTimeOffset = System.DateTimeOffset = TypeCode.Object
|
|
case TypeCode.Decimal:
|
|
primitiveTypeKind = PrimitiveTypeKind.Decimal;
|
|
break;
|
|
case TypeCode.Double:
|
|
primitiveTypeKind = PrimitiveTypeKind.Double;
|
|
break;
|
|
// PrimitiveTypeKind.Geography = System.Data.Spatial.DbGeometry (or subtype) = TypeCode.Object
|
|
// PrimitiveTypeKind.Geometry = System.Data.Spatial.DbGeometry (or subtype) = TypeCode.Object
|
|
// PrimitiveTypeKind.Guid = System.Guid = TypeCode.Object
|
|
case TypeCode.Int16:
|
|
primitiveTypeKind = PrimitiveTypeKind.Int16;
|
|
break;
|
|
case TypeCode.Int32:
|
|
primitiveTypeKind = PrimitiveTypeKind.Int32;
|
|
break;
|
|
case TypeCode.Int64:
|
|
primitiveTypeKind = PrimitiveTypeKind.Int64;
|
|
break;
|
|
case TypeCode.SByte:
|
|
primitiveTypeKind = PrimitiveTypeKind.SByte;
|
|
break;
|
|
case TypeCode.Single:
|
|
primitiveTypeKind = PrimitiveTypeKind.Single;
|
|
break;
|
|
case TypeCode.String:
|
|
primitiveTypeKind = PrimitiveTypeKind.String;
|
|
break;
|
|
// PrimitiveTypeKind.Time = System.TimeSpan = TypeCode.Object
|
|
case TypeCode.Object:
|
|
{
|
|
if (typeof(byte[]) == clrType)
|
|
{
|
|
primitiveTypeKind = PrimitiveTypeKind.Binary;
|
|
}
|
|
else if (typeof(DateTimeOffset) == clrType)
|
|
{
|
|
primitiveTypeKind = PrimitiveTypeKind.DateTimeOffset;
|
|
}
|
|
// DbGeography/Geometry are abstract so subtypes must be allowed
|
|
else if (typeof(System.Data.Spatial.DbGeography).IsAssignableFrom(clrType))
|
|
{
|
|
primitiveTypeKind = PrimitiveTypeKind.Geography;
|
|
}
|
|
else if (typeof(System.Data.Spatial.DbGeometry).IsAssignableFrom(clrType))
|
|
{
|
|
primitiveTypeKind = PrimitiveTypeKind.Geometry;
|
|
}
|
|
else if (typeof(Guid) == clrType)
|
|
{
|
|
primitiveTypeKind = PrimitiveTypeKind.Guid;
|
|
}
|
|
else if (typeof(TimeSpan) == clrType)
|
|
{
|
|
primitiveTypeKind = PrimitiveTypeKind.Time;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (primitiveTypeKind.HasValue)
|
|
{
|
|
resolvedPrimitiveTypeKind = primitiveTypeKind.Value;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
resolvedPrimitiveTypeKind = default(PrimitiveTypeKind);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns all the functions in this provider manifest
|
|
/// </summary>
|
|
/// <returns>A collection of functions</returns>
|
|
public override System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> GetStoreFunctions()
|
|
{
|
|
return Helper.EmptyEdmFunctionReadOnlyCollection;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns all the FacetDescriptions for a particular type
|
|
/// </summary>
|
|
/// <param name="type">the type to return FacetDescriptions for.</param>
|
|
/// <returns>The FacetDescriptions for the type given.</returns>
|
|
public override System.Collections.ObjectModel.ReadOnlyCollection<FacetDescription> GetFacetDescriptions(EdmType type)
|
|
{
|
|
if (Helper.IsPrimitiveType(type) && ((PrimitiveType)type).DataSpace == DataSpace.OSpace)
|
|
{
|
|
// we don't have our own facets, just defer to the edm primitive type facets
|
|
PrimitiveType basePrimitive = (PrimitiveType)type.BaseType;
|
|
return basePrimitive.ProviderManifest.GetFacetDescriptions(basePrimitive);
|
|
}
|
|
|
|
return Helper.EmptyFacetDescriptionEnumerable;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes all the primitive types
|
|
/// </summary>
|
|
private void InitializePrimitiveTypes()
|
|
{
|
|
if (_primitiveTypes != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PrimitiveType[] primitiveTypes = new PrimitiveType[s_PrimitiveTypeCount];
|
|
primitiveTypes[(int)PrimitiveTypeKind.Binary] = CreatePrimitiveType(typeof(Byte[]), PrimitiveTypeKind.Binary);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Boolean] = CreatePrimitiveType(typeof(Boolean), PrimitiveTypeKind.Boolean);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Byte] = CreatePrimitiveType(typeof(Byte), PrimitiveTypeKind.Byte);
|
|
primitiveTypes[(int)PrimitiveTypeKind.DateTime] = CreatePrimitiveType(typeof(DateTime), PrimitiveTypeKind.DateTime);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Time] = CreatePrimitiveType(typeof(TimeSpan), PrimitiveTypeKind.Time);
|
|
primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset] = CreatePrimitiveType(typeof(DateTimeOffset), PrimitiveTypeKind.DateTimeOffset);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Decimal] = CreatePrimitiveType(typeof(Decimal), PrimitiveTypeKind.Decimal);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Double] = CreatePrimitiveType(typeof(Double), PrimitiveTypeKind.Double);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Geography] = CreatePrimitiveType(typeof(DbGeography), PrimitiveTypeKind.Geography);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Geometry] = CreatePrimitiveType(typeof(DbGeometry), PrimitiveTypeKind.Geometry);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Guid] = CreatePrimitiveType(typeof(Guid), PrimitiveTypeKind.Guid);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Int16] = CreatePrimitiveType(typeof(Int16), PrimitiveTypeKind.Int16);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Int32] = CreatePrimitiveType(typeof(Int32), PrimitiveTypeKind.Int32);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Int64] = CreatePrimitiveType(typeof(Int64), PrimitiveTypeKind.Int64);
|
|
primitiveTypes[(int)PrimitiveTypeKind.SByte] = CreatePrimitiveType(typeof(SByte), PrimitiveTypeKind.SByte);
|
|
primitiveTypes[(int)PrimitiveTypeKind.Single] = CreatePrimitiveType(typeof(Single), PrimitiveTypeKind.Single);
|
|
primitiveTypes[(int)PrimitiveTypeKind.String] = CreatePrimitiveType(typeof(String), PrimitiveTypeKind.String);
|
|
|
|
System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType> readOnlyTypes = new System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType>(primitiveTypes);
|
|
|
|
// Set the result to _primitiveTypes at the end
|
|
Interlocked.CompareExchange<System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType>>(ref _primitiveTypes, readOnlyTypes, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize the primitive type with the given
|
|
/// </summary>
|
|
/// <param name="clrType">The CLR type of this type</param>
|
|
/// <param name="primitiveTypeKind">The primitive type kind of the primitive type</param>
|
|
private PrimitiveType CreatePrimitiveType(Type clrType, PrimitiveTypeKind primitiveTypeKind)
|
|
{
|
|
// Figures out the base type
|
|
PrimitiveType baseType = MetadataItem.EdmProviderManifest.GetPrimitiveType(primitiveTypeKind);
|
|
PrimitiveType primitiveType = new PrimitiveType(clrType, baseType, this);
|
|
primitiveType.SetReadOnly();
|
|
return primitiveType;
|
|
}
|
|
|
|
|
|
public override System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType> GetStoreTypes()
|
|
{
|
|
InitializePrimitiveTypes();
|
|
return this._primitiveTypes;
|
|
}
|
|
|
|
public override TypeUsage GetEdmType(TypeUsage storeType)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override TypeUsage GetStoreType(TypeUsage edmType)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Providers should override this to return information specific to their provider.
|
|
///
|
|
/// This method should never return null.
|
|
/// </summary>
|
|
/// <param name="informationType">The name of the information to be retrieved.</param>
|
|
/// <returns>An XmlReader at the begining of the information requested.</returns>
|
|
protected override System.Xml.XmlReader GetDbInformation(string informationType)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|