1 //---------------------------------------------------------------------
2 // <copyright file="ClrProviderManifest.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 using System
.Collections
.Generic
;
11 using System
.Data
.Common
;
12 using System
.Diagnostics
;
13 using System
.Collections
.ObjectModel
;
14 using System
.Data
.Spatial
;
15 using System
.Threading
;
18 namespace System
.Data
.Metadata
.Edm
20 internal class ClrProviderManifest
: DbProviderManifest
22 private const int s_PrimitiveTypeCount
= 17;
23 private System
.Collections
.ObjectModel
.ReadOnlyCollection
<PrimitiveType
> _primitiveTypes
;
24 private static ClrProviderManifest _instance
= new ClrProviderManifest();
27 /// A private constructor to prevent other places from instantiating this class
29 private ClrProviderManifest()
34 /// Gets the EDM provider manifest singleton instance
36 internal static ClrProviderManifest Instance
45 /// Returns the namespace used by this provider manifest
47 public override string NamespaceName
49 get { return EdmConstants.ClrPrimitiveTypeNamespace; }
53 /// Returns the primitive type corresponding to the given CLR type
55 /// <param name="clrType">The CLR type for which the PrimitiveType object is retrieved</param>
56 /// <param name="primitiveType">The retrieved primitive type</param>
57 /// <returns>True if a primitive type is returned</returns>
58 internal bool TryGetPrimitiveType(Type clrType
, out PrimitiveType primitiveType
)
61 PrimitiveTypeKind resolvedTypeKind
;
62 if (TryGetPrimitiveTypeKind(clrType
, out resolvedTypeKind
))
64 InitializePrimitiveTypes();
65 primitiveType
= _primitiveTypes
[(int)resolvedTypeKind
];
73 /// Returns the <see cref="PrimitiveTypeKind"/> corresponding to the given CLR type
75 /// <param name="clrType">The CLR type for which the PrimitiveTypeKind value should be resolved</param>
76 /// <param name="primitiveType">The PrimitiveTypeKind value to which the CLR type resolves, if any.</param>
77 /// <returns>True if the CLR type represents a primitive (EDM) type; otherwise false.</returns>
78 internal bool TryGetPrimitiveTypeKind(Type clrType
, out PrimitiveTypeKind resolvedPrimitiveTypeKind
)
80 PrimitiveTypeKind
? primitiveTypeKind
= null;
81 if (!clrType
.IsEnum
) // Enums return the TypeCode of their underlying type
83 // As an optimization, short-circuit when the provided type has a known type code.
84 switch (Type
.GetTypeCode(clrType
))
86 // PrimitiveTypeKind.Binary = byte[] = TypeCode.Object
87 case TypeCode
.Boolean
:
88 primitiveTypeKind
= PrimitiveTypeKind
.Boolean
;
91 primitiveTypeKind
= PrimitiveTypeKind
.Byte
;
93 case TypeCode
.DateTime
:
94 primitiveTypeKind
= PrimitiveTypeKind
.DateTime
;
96 // PrimitiveTypeKind.DateTimeOffset = System.DateTimeOffset = TypeCode.Object
97 case TypeCode
.Decimal
:
98 primitiveTypeKind
= PrimitiveTypeKind
.Decimal
;
100 case TypeCode
.Double
:
101 primitiveTypeKind
= PrimitiveTypeKind
.Double
;
103 // PrimitiveTypeKind.Geography = System.Data.Spatial.DbGeometry (or subtype) = TypeCode.Object
104 // PrimitiveTypeKind.Geometry = System.Data.Spatial.DbGeometry (or subtype) = TypeCode.Object
105 // PrimitiveTypeKind.Guid = System.Guid = TypeCode.Object
107 primitiveTypeKind
= PrimitiveTypeKind
.Int16
;
110 primitiveTypeKind
= PrimitiveTypeKind
.Int32
;
113 primitiveTypeKind
= PrimitiveTypeKind
.Int64
;
116 primitiveTypeKind
= PrimitiveTypeKind
.SByte
;
118 case TypeCode
.Single
:
119 primitiveTypeKind
= PrimitiveTypeKind
.Single
;
121 case TypeCode
.String
:
122 primitiveTypeKind
= PrimitiveTypeKind
.String
;
124 // PrimitiveTypeKind.Time = System.TimeSpan = TypeCode.Object
125 case TypeCode
.Object
:
127 if (typeof(byte[]) == clrType
)
129 primitiveTypeKind
= PrimitiveTypeKind
.Binary
;
131 else if (typeof(DateTimeOffset
) == clrType
)
133 primitiveTypeKind
= PrimitiveTypeKind
.DateTimeOffset
;
135 // DbGeography/Geometry are abstract so subtypes must be allowed
136 else if (typeof(System
.Data
.Spatial
.DbGeography
).IsAssignableFrom(clrType
))
138 primitiveTypeKind
= PrimitiveTypeKind
.Geography
;
140 else if (typeof(System
.Data
.Spatial
.DbGeometry
).IsAssignableFrom(clrType
))
142 primitiveTypeKind
= PrimitiveTypeKind
.Geometry
;
144 else if (typeof(Guid
) == clrType
)
146 primitiveTypeKind
= PrimitiveTypeKind
.Guid
;
148 else if (typeof(TimeSpan
) == clrType
)
150 primitiveTypeKind
= PrimitiveTypeKind
.Time
;
157 if (primitiveTypeKind
.HasValue
)
159 resolvedPrimitiveTypeKind
= primitiveTypeKind
.Value
;
164 resolvedPrimitiveTypeKind
= default(PrimitiveTypeKind
);
170 /// Returns all the functions in this provider manifest
172 /// <returns>A collection of functions</returns>
173 public override System
.Collections
.ObjectModel
.ReadOnlyCollection
<EdmFunction
> GetStoreFunctions()
175 return Helper
.EmptyEdmFunctionReadOnlyCollection
;
179 /// Returns all the FacetDescriptions for a particular type
181 /// <param name="type">the type to return FacetDescriptions for.</param>
182 /// <returns>The FacetDescriptions for the type given.</returns>
183 public override System
.Collections
.ObjectModel
.ReadOnlyCollection
<FacetDescription
> GetFacetDescriptions(EdmType type
)
185 if (Helper
.IsPrimitiveType(type
) && ((PrimitiveType
)type
).DataSpace
== DataSpace
.OSpace
)
187 // we don't have our own facets, just defer to the edm primitive type facets
188 PrimitiveType basePrimitive
= (PrimitiveType
)type
.BaseType
;
189 return basePrimitive
.ProviderManifest
.GetFacetDescriptions(basePrimitive
);
192 return Helper
.EmptyFacetDescriptionEnumerable
;
196 /// Initializes all the primitive types
198 private void InitializePrimitiveTypes()
200 if (_primitiveTypes
!= null)
205 PrimitiveType
[] primitiveTypes
= new PrimitiveType
[s_PrimitiveTypeCount
];
206 primitiveTypes
[(int)PrimitiveTypeKind
.Binary
] = CreatePrimitiveType(typeof(Byte
[]), PrimitiveTypeKind
.Binary
);
207 primitiveTypes
[(int)PrimitiveTypeKind
.Boolean
] = CreatePrimitiveType(typeof(Boolean
), PrimitiveTypeKind
.Boolean
);
208 primitiveTypes
[(int)PrimitiveTypeKind
.Byte
] = CreatePrimitiveType(typeof(Byte
), PrimitiveTypeKind
.Byte
);
209 primitiveTypes
[(int)PrimitiveTypeKind
.DateTime
] = CreatePrimitiveType(typeof(DateTime
), PrimitiveTypeKind
.DateTime
);
210 primitiveTypes
[(int)PrimitiveTypeKind
.Time
] = CreatePrimitiveType(typeof(TimeSpan
), PrimitiveTypeKind
.Time
);
211 primitiveTypes
[(int)PrimitiveTypeKind
.DateTimeOffset
] = CreatePrimitiveType(typeof(DateTimeOffset
), PrimitiveTypeKind
.DateTimeOffset
);
212 primitiveTypes
[(int)PrimitiveTypeKind
.Decimal
] = CreatePrimitiveType(typeof(Decimal
), PrimitiveTypeKind
.Decimal
);
213 primitiveTypes
[(int)PrimitiveTypeKind
.Double
] = CreatePrimitiveType(typeof(Double
), PrimitiveTypeKind
.Double
);
214 primitiveTypes
[(int)PrimitiveTypeKind
.Geography
] = CreatePrimitiveType(typeof(DbGeography
), PrimitiveTypeKind
.Geography
);
215 primitiveTypes
[(int)PrimitiveTypeKind
.Geometry
] = CreatePrimitiveType(typeof(DbGeometry
), PrimitiveTypeKind
.Geometry
);
216 primitiveTypes
[(int)PrimitiveTypeKind
.Guid
] = CreatePrimitiveType(typeof(Guid
), PrimitiveTypeKind
.Guid
);
217 primitiveTypes
[(int)PrimitiveTypeKind
.Int16
] = CreatePrimitiveType(typeof(Int16
), PrimitiveTypeKind
.Int16
);
218 primitiveTypes
[(int)PrimitiveTypeKind
.Int32
] = CreatePrimitiveType(typeof(Int32
), PrimitiveTypeKind
.Int32
);
219 primitiveTypes
[(int)PrimitiveTypeKind
.Int64
] = CreatePrimitiveType(typeof(Int64
), PrimitiveTypeKind
.Int64
);
220 primitiveTypes
[(int)PrimitiveTypeKind
.SByte
] = CreatePrimitiveType(typeof(SByte
), PrimitiveTypeKind
.SByte
);
221 primitiveTypes
[(int)PrimitiveTypeKind
.Single
] = CreatePrimitiveType(typeof(Single
), PrimitiveTypeKind
.Single
);
222 primitiveTypes
[(int)PrimitiveTypeKind
.String
] = CreatePrimitiveType(typeof(String
), PrimitiveTypeKind
.String
);
224 System
.Collections
.ObjectModel
.ReadOnlyCollection
<PrimitiveType
> readOnlyTypes
= new System
.Collections
.ObjectModel
.ReadOnlyCollection
<PrimitiveType
>(primitiveTypes
);
226 // Set the result to _primitiveTypes at the end
227 Interlocked
.CompareExchange
<System
.Collections
.ObjectModel
.ReadOnlyCollection
<PrimitiveType
>>(ref _primitiveTypes
, readOnlyTypes
, null);
231 /// Initialize the primitive type with the given
233 /// <param name="clrType">The CLR type of this type</param>
234 /// <param name="primitiveTypeKind">The primitive type kind of the primitive type</param>
235 private PrimitiveType
CreatePrimitiveType(Type clrType
, PrimitiveTypeKind primitiveTypeKind
)
237 // Figures out the base type
238 PrimitiveType baseType
= MetadataItem
.EdmProviderManifest
.GetPrimitiveType(primitiveTypeKind
);
239 PrimitiveType primitiveType
= new PrimitiveType(clrType
, baseType
, this);
240 primitiveType
.SetReadOnly();
241 return primitiveType
;
245 public override System
.Collections
.ObjectModel
.ReadOnlyCollection
<PrimitiveType
> GetStoreTypes()
247 InitializePrimitiveTypes();
248 return this._primitiveTypes
;
251 public override TypeUsage
GetEdmType(TypeUsage storeType
)
253 throw new NotImplementedException();
256 public override TypeUsage
GetStoreType(TypeUsage edmType
)
258 throw new NotImplementedException();
262 /// Providers should override this to return information specific to their provider.
264 /// This method should never return null.
266 /// <param name="informationType">The name of the information to be retrieved.</param>
267 /// <returns>An XmlReader at the begining of the information requested.</returns>
268 protected override System
.Xml
.XmlReader
GetDbInformation(string informationType
)
270 throw new NotImplementedException();