PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/src/System.Web.Http.OData/OData/Formatter/EdmLibHelpers.cs

http://aspnetwebstack.codeplex.com
C# | 486 lines | 415 code | 54 blank | 17 comment | 105 complexity | f4dd36c07dc6aa8a2aa7878f90709ec8 MD5 | raw file
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. using System.Collections.Generic;
  3. using System.Data.Linq;
  4. using System.Diagnostics.Contracts;
  5. using System.Globalization;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Runtime.Serialization;
  9. using System.Spatial;
  10. using System.Web.Http.Dispatcher;
  11. using System.Web.Http.OData.Formatter.Deserialization;
  12. using System.Web.Http.OData.Properties;
  13. using System.Xml.Linq;
  14. using Microsoft.Data.Edm;
  15. using Microsoft.Data.Edm.Library;
  16. namespace System.Web.Http.OData.Formatter
  17. {
  18. internal static class EdmLibHelpers
  19. {
  20. private static readonly EdmCoreModel _coreModel = EdmCoreModel.Instance;
  21. private static readonly IAssembliesResolver _defaultAssemblyResolver = new DefaultAssembliesResolver();
  22. private static readonly Dictionary<Type, IEdmPrimitiveType> _builtInTypesMapping =
  23. new[]
  24. {
  25. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(string), GetPrimitiveType(EdmPrimitiveTypeKind.String)),
  26. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(bool), GetPrimitiveType(EdmPrimitiveTypeKind.Boolean)),
  27. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(bool?), GetPrimitiveType(EdmPrimitiveTypeKind.Boolean)),
  28. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(byte), GetPrimitiveType(EdmPrimitiveTypeKind.Byte)),
  29. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(byte?), GetPrimitiveType(EdmPrimitiveTypeKind.Byte)),
  30. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(DateTime), GetPrimitiveType(EdmPrimitiveTypeKind.DateTime)),
  31. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(DateTime?), GetPrimitiveType(EdmPrimitiveTypeKind.DateTime)),
  32. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(decimal), GetPrimitiveType(EdmPrimitiveTypeKind.Decimal)),
  33. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(decimal?), GetPrimitiveType(EdmPrimitiveTypeKind.Decimal)),
  34. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(double), GetPrimitiveType(EdmPrimitiveTypeKind.Double)),
  35. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(double?), GetPrimitiveType(EdmPrimitiveTypeKind.Double)),
  36. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(Guid), GetPrimitiveType(EdmPrimitiveTypeKind.Guid)),
  37. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(Guid?), GetPrimitiveType(EdmPrimitiveTypeKind.Guid)),
  38. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(short), GetPrimitiveType(EdmPrimitiveTypeKind.Int16)),
  39. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(short?), GetPrimitiveType(EdmPrimitiveTypeKind.Int16)),
  40. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(int), GetPrimitiveType(EdmPrimitiveTypeKind.Int32)),
  41. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(int?), GetPrimitiveType(EdmPrimitiveTypeKind.Int32)),
  42. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(long), GetPrimitiveType(EdmPrimitiveTypeKind.Int64)),
  43. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(long?), GetPrimitiveType(EdmPrimitiveTypeKind.Int64)),
  44. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(sbyte), GetPrimitiveType(EdmPrimitiveTypeKind.SByte)),
  45. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(sbyte?), GetPrimitiveType(EdmPrimitiveTypeKind.SByte)),
  46. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(float), GetPrimitiveType(EdmPrimitiveTypeKind.Single)),
  47. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(float?), GetPrimitiveType(EdmPrimitiveTypeKind.Single)),
  48. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(byte[]), GetPrimitiveType(EdmPrimitiveTypeKind.Binary)),
  49. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(Stream), GetPrimitiveType(EdmPrimitiveTypeKind.Stream)),
  50. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(Geography), GetPrimitiveType(EdmPrimitiveTypeKind.Geography)),
  51. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeographyPoint), GetPrimitiveType(EdmPrimitiveTypeKind.GeographyPoint)),
  52. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeographyLineString), GetPrimitiveType(EdmPrimitiveTypeKind.GeographyLineString)),
  53. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeographyPolygon), GetPrimitiveType(EdmPrimitiveTypeKind.GeographyPolygon)),
  54. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeographyCollection), GetPrimitiveType(EdmPrimitiveTypeKind.GeographyCollection)),
  55. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeographyMultiLineString), GetPrimitiveType(EdmPrimitiveTypeKind.GeographyMultiLineString)),
  56. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeographyMultiPoint), GetPrimitiveType(EdmPrimitiveTypeKind.GeographyMultiPoint)),
  57. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeographyMultiPolygon), GetPrimitiveType(EdmPrimitiveTypeKind.GeographyMultiPolygon)),
  58. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(Geometry), GetPrimitiveType(EdmPrimitiveTypeKind.Geometry)),
  59. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeometryPoint), GetPrimitiveType(EdmPrimitiveTypeKind.GeometryPoint)),
  60. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeometryLineString), GetPrimitiveType(EdmPrimitiveTypeKind.GeometryLineString)),
  61. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeometryPolygon), GetPrimitiveType(EdmPrimitiveTypeKind.GeometryPolygon)),
  62. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeometryCollection), GetPrimitiveType(EdmPrimitiveTypeKind.GeometryCollection)),
  63. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeometryMultiLineString), GetPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiLineString)),
  64. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeometryMultiPoint), GetPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiPoint)),
  65. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(GeometryMultiPolygon), GetPrimitiveType(EdmPrimitiveTypeKind.GeometryMultiPolygon)),
  66. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(TimeSpan), GetPrimitiveType(EdmPrimitiveTypeKind.Time)),
  67. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(TimeSpan?), GetPrimitiveType(EdmPrimitiveTypeKind.Time)),
  68. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(DateTimeOffset), GetPrimitiveType(EdmPrimitiveTypeKind.DateTimeOffset)),
  69. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(DateTimeOffset?), GetPrimitiveType(EdmPrimitiveTypeKind.DateTimeOffset)),
  70. // Keep the Binary and XElement in the end, since there are not the default mappings for Edm.Binary and Edm.String.
  71. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(XElement), GetPrimitiveType(EdmPrimitiveTypeKind.String)),
  72. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(Binary), GetPrimitiveType(EdmPrimitiveTypeKind.Binary)),
  73. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(ushort), GetPrimitiveType(EdmPrimitiveTypeKind.Int32)),
  74. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(ushort?), GetPrimitiveType(EdmPrimitiveTypeKind.Int32)),
  75. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(uint), GetPrimitiveType(EdmPrimitiveTypeKind.Int64)),
  76. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(uint?), GetPrimitiveType(EdmPrimitiveTypeKind.Int64)),
  77. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(ulong), GetPrimitiveType(EdmPrimitiveTypeKind.Int64)),
  78. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(ulong?), GetPrimitiveType(EdmPrimitiveTypeKind.Int64)),
  79. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(char[]), GetPrimitiveType(EdmPrimitiveTypeKind.String)),
  80. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(char), GetPrimitiveType(EdmPrimitiveTypeKind.String)),
  81. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(char?), GetPrimitiveType(EdmPrimitiveTypeKind.String)),
  82. }
  83. .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
  84. public static IEdmType GetEdmType(this IEdmModel edmModel, Type clrType)
  85. {
  86. if (edmModel == null)
  87. {
  88. throw Error.ArgumentNull("edmModel");
  89. }
  90. if (clrType == null)
  91. {
  92. throw Error.ArgumentNull("clrType");
  93. }
  94. IEdmPrimitiveType primitiveType = GetEdmPrimitiveTypeOrNull(clrType);
  95. if (primitiveType != null)
  96. {
  97. return primitiveType;
  98. }
  99. else
  100. {
  101. Type enumerableOfT = ExtractGenericInterface(clrType, typeof(IEnumerable<>));
  102. if (enumerableOfT != null)
  103. {
  104. IEdmTypeReference elementType = GetEdmTypeReference(edmModel, enumerableOfT.GetGenericArguments()[0]);
  105. if (elementType != null)
  106. {
  107. return new EdmCollectionType(elementType);
  108. }
  109. }
  110. // search for the ClrTypeAnnotation and return it if present
  111. IEdmType returnType =
  112. edmModel
  113. .SchemaElements
  114. .OfType<IEdmType>()
  115. .Select(edmType => new { EdmType = edmType, Annotation = edmModel.GetAnnotationValue<ClrTypeAnnotation>(edmType) })
  116. .Where(tuple => tuple.Annotation != null && tuple.Annotation.ClrType == clrType)
  117. .Select(tuple => tuple.EdmType)
  118. .SingleOrDefault();
  119. // default to the EdmType with the same name as the ClrType name
  120. returnType = returnType ?? edmModel.FindType(clrType.EdmFullName());
  121. if (clrType.BaseType != null)
  122. {
  123. // go up the inheritance tree to see if we have a mapping defined for the base type.
  124. returnType = returnType ?? edmModel.GetEdmType(clrType.BaseType);
  125. }
  126. return returnType;
  127. }
  128. }
  129. public static IEdmTypeReference GetEdmTypeReference(this IEdmModel edmModel, Type clrType)
  130. {
  131. IEdmType edmType = edmModel.GetEdmType(clrType);
  132. if (edmType != null)
  133. {
  134. bool isNullable = IsNullable(clrType);
  135. switch (edmType.TypeKind)
  136. {
  137. case EdmTypeKind.Collection:
  138. return new EdmCollectionTypeReference(edmType as IEdmCollectionType, isNullable);
  139. case EdmTypeKind.Complex:
  140. return new EdmComplexTypeReference(edmType as IEdmComplexType, isNullable);
  141. case EdmTypeKind.Entity:
  142. return new EdmEntityTypeReference(edmType as IEdmEntityType, isNullable);
  143. case EdmTypeKind.EntityReference:
  144. return new EdmEntityReferenceTypeReference(edmType as IEdmEntityReferenceType, isNullable);
  145. case EdmTypeKind.Enum:
  146. return new EdmEnumTypeReference(edmType as IEdmEnumType, isNullable);
  147. case EdmTypeKind.Primitive:
  148. return _coreModel.GetPrimitive((edmType as IEdmPrimitiveType).PrimitiveKind, isNullable);
  149. case EdmTypeKind.Row:
  150. return new EdmRowTypeReference(edmType as IEdmRowType, isNullable);
  151. default:
  152. throw Error.NotSupported(SRResources.EdmTypeNotSupported, edmType.ToTraceString());
  153. }
  154. }
  155. return null;
  156. }
  157. public static IEdmCollectionType GetCollection(this IEdmEntityType entityType)
  158. {
  159. return new EdmCollectionType(new EdmEntityTypeReference(entityType, isNullable: false));
  160. }
  161. public static bool CanBindTo(this IEdmFunctionImport function, IEdmEntityType entity)
  162. {
  163. if (function == null)
  164. {
  165. throw Error.ArgumentNull("function");
  166. }
  167. if (entity == null)
  168. {
  169. throw Error.ArgumentNull("entity");
  170. }
  171. if (!function.IsBindable)
  172. {
  173. return false;
  174. }
  175. // The binding parameter is the first parameter by convention
  176. IEdmFunctionParameter bindingParameter = function.Parameters.FirstOrDefault();
  177. if (bindingParameter == null)
  178. {
  179. return false;
  180. }
  181. IEdmEntityType bindingParameterType = bindingParameter.Type.Definition as IEdmEntityType;
  182. if (bindingParameterType == null)
  183. {
  184. return false;
  185. }
  186. return entity.IsOrInheritsFrom(bindingParameterType);
  187. }
  188. public static bool CanBindTo(this IEdmFunctionImport function, IEdmCollectionType collection)
  189. {
  190. if (function == null)
  191. {
  192. throw Error.ArgumentNull("function");
  193. }
  194. if (collection == null)
  195. {
  196. throw Error.ArgumentNull("collection");
  197. }
  198. if (!function.IsBindable)
  199. {
  200. return false;
  201. }
  202. // The binding parameter is the first parameter by convention
  203. IEdmFunctionParameter bindingParameter = function.Parameters.FirstOrDefault();
  204. if (bindingParameter == null)
  205. {
  206. return false;
  207. }
  208. IEdmCollectionType bindingParameterType = bindingParameter.Type.Definition as IEdmCollectionType;
  209. if (bindingParameterType == null)
  210. {
  211. return false;
  212. }
  213. IEdmEntityType bindingParameterElementType = bindingParameterType.ElementType.Definition as IEdmEntityType;
  214. IEdmEntityType entity = collection.ElementType.Definition as IEdmEntityType;
  215. if (bindingParameterElementType == null || entity == null)
  216. {
  217. return false;
  218. }
  219. return entity.IsOrInheritsFrom(bindingParameterElementType);
  220. }
  221. public static IEnumerable<IEdmFunctionImport> GetMatchingActions(this IEnumerable<IEdmFunctionImport> functions, string actionIdentifier)
  222. {
  223. if (functions == null)
  224. {
  225. throw Error.ArgumentNull("functions");
  226. }
  227. if (actionIdentifier == null)
  228. {
  229. throw Error.ArgumentNull("actionIdentifier");
  230. }
  231. string[] nameParts = actionIdentifier.Split('.');
  232. Contract.Assert(nameParts.Length != 0);
  233. if (nameParts.Length == 1)
  234. {
  235. // Name
  236. string name = nameParts[0];
  237. return functions.Where(f => f.IsSideEffecting && f.Name == name);
  238. }
  239. else if (nameParts.Length == 2)
  240. {
  241. // Container.Name
  242. string name = nameParts[nameParts.Length - 1];
  243. string container = nameParts[nameParts.Length - 2];
  244. return functions.Where(f => f.IsSideEffecting && f.Name == name && f.Container.Name == container);
  245. }
  246. else
  247. {
  248. // Namespace.Container.Name
  249. string name = nameParts[nameParts.Length - 1];
  250. string container = nameParts[nameParts.Length - 2];
  251. string nspace = String.Join(".", nameParts.Take(nameParts.Length - 2));
  252. return functions.Where(f => f.IsSideEffecting && f.Name == name && f.Container.Name == container && f.Container.Namespace == nspace);
  253. }
  254. }
  255. public static IEdmFunctionImport FindBindableAction(this IEnumerable<IEdmFunctionImport> functions, IEdmEntityType entityType, string actionIdentifier)
  256. {
  257. if (functions == null)
  258. {
  259. throw Error.ArgumentNull("functions");
  260. }
  261. if (entityType == null)
  262. {
  263. throw Error.ArgumentNull("entityType");
  264. }
  265. if (actionIdentifier == null)
  266. {
  267. throw Error.ArgumentNull("actionIdentifier");
  268. }
  269. IEdmFunctionImport[] matches = functions.GetMatchingActions(actionIdentifier).Where(fi => fi.CanBindTo(entityType)).ToArray();
  270. if (matches.Length > 1)
  271. {
  272. throw Error.Argument(
  273. "actionIdentifier",
  274. SRResources.ActionResolutionFailed,
  275. actionIdentifier,
  276. String.Join(", ", matches.Select(match => match.Container.FullName() + "." + match.Name)));
  277. }
  278. else if (matches.Length == 1)
  279. {
  280. return matches[0];
  281. }
  282. else
  283. {
  284. return null;
  285. }
  286. }
  287. public static IEdmFunctionImport FindBindableAction(this IEnumerable<IEdmFunctionImport> functions, IEdmCollectionType collectionType, string actionIdentifier)
  288. {
  289. if (functions == null)
  290. {
  291. throw Error.ArgumentNull("functions");
  292. }
  293. if (collectionType == null)
  294. {
  295. throw Error.ArgumentNull("collectionType");
  296. }
  297. if (actionIdentifier == null)
  298. {
  299. throw Error.ArgumentNull("actionIdentifier");
  300. }
  301. IEdmFunctionImport[] matches = functions.GetMatchingActions(actionIdentifier).Where(fi => fi.CanBindTo(collectionType)).ToArray();
  302. if (matches.Length > 1)
  303. {
  304. IEdmEntityType elementType = collectionType.ElementType as IEdmEntityType;
  305. Contract.Assert(elementType != null);
  306. throw Error.Argument(
  307. "actionIdentifier",
  308. SRResources.ActionResolutionFailed,
  309. actionIdentifier,
  310. String.Join(", ", matches.Select(match => match.Container.FullName() + "." + match.Name)));
  311. }
  312. else if (matches.Length == 1)
  313. {
  314. return matches[0];
  315. }
  316. else
  317. {
  318. return null;
  319. }
  320. }
  321. public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmModel)
  322. {
  323. return GetClrType(edmTypeReference, edmModel, _defaultAssemblyResolver);
  324. }
  325. public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmModel, IAssembliesResolver assembliesResolver)
  326. {
  327. if (edmTypeReference == null)
  328. {
  329. throw Error.ArgumentNull("edmTypeReference");
  330. }
  331. Type primitiveClrType = _builtInTypesMapping
  332. .Where(kvp => edmTypeReference.Definition.IsEquivalentTo(kvp.Value) && (!edmTypeReference.IsNullable || IsNullable(kvp.Key)))
  333. .Select(kvp => kvp.Key)
  334. .FirstOrDefault();
  335. if (primitiveClrType != null)
  336. {
  337. return primitiveClrType;
  338. }
  339. else
  340. {
  341. ClrTypeAnnotation annotation = edmModel.GetAnnotationValue<ClrTypeAnnotation>(edmTypeReference.Definition);
  342. if (annotation != null)
  343. {
  344. return annotation.ClrType;
  345. }
  346. IEnumerable<Type> matchingTypes = GetMatchingTypes(edmTypeReference.FullName(), assembliesResolver);
  347. if (matchingTypes.Count() > 1)
  348. {
  349. throw Error.Argument("edmTypeReference", SRResources.MultipleMatchingClrTypesForEdmType,
  350. edmTypeReference.FullName(), String.Join(",", matchingTypes.Select(type => type.AssemblyQualifiedName)));
  351. }
  352. edmModel.SetAnnotationValue<ClrTypeAnnotation>(edmTypeReference.Definition, new ClrTypeAnnotation(matchingTypes.SingleOrDefault()));
  353. return matchingTypes.SingleOrDefault();
  354. }
  355. }
  356. public static IEdmPrimitiveType GetEdmPrimitiveTypeOrNull(Type clrType)
  357. {
  358. Type underlyingType = Nullable.GetUnderlyingType(clrType) ?? clrType;
  359. if (underlyingType.IsEnum)
  360. {
  361. // Enums are treated as strings
  362. clrType = typeof(string);
  363. }
  364. IEdmPrimitiveType primitiveType;
  365. return _builtInTypesMapping.TryGetValue(clrType, out primitiveType) ? primitiveType : null;
  366. }
  367. public static IEdmPrimitiveTypeReference GetEdmPrimitiveTypeReferenceOrNull(Type clrType)
  368. {
  369. IEdmPrimitiveType primitiveType = GetEdmPrimitiveTypeOrNull(clrType);
  370. return primitiveType != null ? _coreModel.GetPrimitive(primitiveType.PrimitiveKind, IsNullable(clrType)) : null;
  371. }
  372. // figures out if the given clr type is nonstandard edm primitive like uint, ushort, char[] etc.
  373. // and returns the corresponding clr type to which we map like uint => long.
  374. public static Type IsNonstandardEdmPrimitive(Type type, out bool isNonstandardEdmPrimitive)
  375. {
  376. IEdmPrimitiveTypeReference edmType = GetEdmPrimitiveTypeReferenceOrNull(type);
  377. if (edmType == null)
  378. {
  379. isNonstandardEdmPrimitive = false;
  380. return type;
  381. }
  382. Type reverseLookupClrType = GetClrType(edmType, EdmCoreModel.Instance);
  383. isNonstandardEdmPrimitive = (type != reverseLookupClrType);
  384. return reverseLookupClrType;
  385. }
  386. // Mangle the invalid EDM literal Type.FullName (System.Collections.Generic.IEnumerable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]])
  387. // to a valid EDM literal (the C# type name IEnumerable<int>).
  388. public static string EdmName(this Type clrType)
  389. {
  390. // We cannot use just Type.Name here as it doesn't work for generic types.
  391. return MangleClrTypeName(clrType);
  392. }
  393. public static string EdmFullName(this Type clrType)
  394. {
  395. return String.Format(CultureInfo.InvariantCulture, "{0}.{1}", clrType.Namespace, clrType.EdmName());
  396. }
  397. private static IEdmPrimitiveType GetPrimitiveType(EdmPrimitiveTypeKind primitiveKind)
  398. {
  399. return _coreModel.GetPrimitiveType(primitiveKind);
  400. }
  401. public static bool IsNullable(Type type)
  402. {
  403. return !type.IsValueType || Nullable.GetUnderlyingType(type) != null;
  404. }
  405. private static Type ExtractGenericInterface(Type queryType, Type interfaceType)
  406. {
  407. Func<Type, bool> matchesInterface = t => t.IsGenericType && t.GetGenericTypeDefinition() == interfaceType;
  408. return matchesInterface(queryType) ? queryType : queryType.GetInterfaces().FirstOrDefault(matchesInterface);
  409. }
  410. private static IEnumerable<Type> GetMatchingTypes(string edmFullName, IAssembliesResolver assembliesResolver)
  411. {
  412. return TypeHelper.GetLoadedTypes(assembliesResolver).Where(t => t.IsPublic && t.EdmFullName() == edmFullName);
  413. }
  414. // TODO (workitem 336): Support nested types and anonymous types.
  415. private static string MangleClrTypeName(Type type)
  416. {
  417. Contract.Assert(type != null);
  418. if (!type.IsGenericType)
  419. {
  420. return type.Name;
  421. }
  422. else
  423. {
  424. return String.Format(
  425. CultureInfo.InvariantCulture,
  426. "{0}Of{1}",
  427. type.Name.Replace('`', '_'),
  428. String.Join("_", type.GetGenericArguments().Select(t => MangleClrTypeName(t))));
  429. }
  430. }
  431. }
  432. }