PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://github.com/huyq2002/aspnetwebstack
C# | 451 lines | 374 code | 65 blank | 12 comment | 73 complexity | 17112e1581271692bce2807c362623bb MD5 | raw file
Possible License(s): Apache-2.0
  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.Reflection;
  9. using System.Web.Http;
  10. using System.Web.Http.Dispatcher;
  11. using System.Web.OData.Builder;
  12. using System.Web.OData.Properties;
  13. using System.Web.OData.Query.Expressions;
  14. using System.Xml.Linq;
  15. using Microsoft.OData.Edm;
  16. using Microsoft.OData.Edm.Library;
  17. using Microsoft.Spatial;
  18. namespace System.Web.OData.Formatter
  19. {
  20. internal static class EdmLibHelpers
  21. {
  22. private static readonly EdmCoreModel _coreModel = EdmCoreModel.Instance;
  23. private static readonly IAssembliesResolver _defaultAssemblyResolver = new DefaultAssembliesResolver();
  24. private static readonly Dictionary<Type, IEdmPrimitiveType> _builtInTypesMapping =
  25. new[]
  26. {
  27. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(string), GetPrimitiveType(EdmPrimitiveTypeKind.String)),
  28. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(bool), GetPrimitiveType(EdmPrimitiveTypeKind.Boolean)),
  29. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(bool?), GetPrimitiveType(EdmPrimitiveTypeKind.Boolean)),
  30. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(byte), GetPrimitiveType(EdmPrimitiveTypeKind.Byte)),
  31. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(byte?), GetPrimitiveType(EdmPrimitiveTypeKind.Byte)),
  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(DateTimeOffset), GetPrimitiveType(EdmPrimitiveTypeKind.DateTimeOffset)),
  67. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(DateTimeOffset?), GetPrimitiveType(EdmPrimitiveTypeKind.DateTimeOffset)),
  68. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(TimeSpan), GetPrimitiveType(EdmPrimitiveTypeKind.Duration)),
  69. new KeyValuePair<Type, IEdmPrimitiveType>(typeof(TimeSpan?), GetPrimitiveType(EdmPrimitiveTypeKind.Duration)),
  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. return GetEdmType(edmModel, clrType, testCollections: true);
  95. }
  96. private static IEdmType GetEdmType(IEdmModel edmModel, Type clrType, bool testCollections)
  97. {
  98. Contract.Assert(edmModel != null);
  99. Contract.Assert(clrType != null);
  100. IEdmPrimitiveType primitiveType = GetEdmPrimitiveTypeOrNull(clrType);
  101. if (primitiveType != null)
  102. {
  103. return primitiveType;
  104. }
  105. else
  106. {
  107. if (testCollections)
  108. {
  109. Type enumerableOfT = ExtractGenericInterface(clrType, typeof(IEnumerable<>));
  110. if (enumerableOfT != null)
  111. {
  112. Type elementClrType = enumerableOfT.GetGenericArguments()[0];
  113. // IEnumerable<SelectExpandWrapper<T>> is a collection of T.
  114. Type entityType;
  115. if (IsSelectExpandWrapper(elementClrType, out entityType))
  116. {
  117. elementClrType = entityType;
  118. }
  119. IEdmType elementType = GetEdmType(edmModel, elementClrType, testCollections: false);
  120. if (elementType != null)
  121. {
  122. return new EdmCollectionType(elementType.ToEdmTypeReference(IsNullable(elementClrType)));
  123. }
  124. }
  125. }
  126. Type underlyingType = TypeHelper.GetUnderlyingTypeOrSelf(clrType);
  127. if (underlyingType.IsEnum)
  128. {
  129. clrType = underlyingType;
  130. }
  131. // search for the ClrTypeAnnotation and return it if present
  132. IEdmType returnType =
  133. edmModel
  134. .SchemaElements
  135. .OfType<IEdmType>()
  136. .Select(edmType => new { EdmType = edmType, Annotation = edmModel.GetAnnotationValue<ClrTypeAnnotation>(edmType) })
  137. .Where(tuple => tuple.Annotation != null && tuple.Annotation.ClrType == clrType)
  138. .Select(tuple => tuple.EdmType)
  139. .SingleOrDefault();
  140. // default to the EdmType with the same name as the ClrType name
  141. returnType = returnType ?? edmModel.FindType(clrType.EdmFullName());
  142. if (clrType.BaseType != null)
  143. {
  144. // go up the inheritance tree to see if we have a mapping defined for the base type.
  145. returnType = returnType ?? GetEdmType(edmModel, clrType.BaseType, testCollections);
  146. }
  147. return returnType;
  148. }
  149. }
  150. public static IEdmTypeReference GetEdmTypeReference(this IEdmModel edmModel, Type clrType)
  151. {
  152. IEdmType edmType = edmModel.GetEdmType(clrType);
  153. if (edmType != null)
  154. {
  155. bool isNullable = IsNullable(clrType);
  156. return ToEdmTypeReference(edmType, isNullable);
  157. }
  158. return null;
  159. }
  160. public static IEdmTypeReference ToEdmTypeReference(this IEdmType edmType, bool isNullable)
  161. {
  162. Contract.Assert(edmType != null);
  163. switch (edmType.TypeKind)
  164. {
  165. case EdmTypeKind.Collection:
  166. return new EdmCollectionTypeReference(edmType as IEdmCollectionType);
  167. case EdmTypeKind.Complex:
  168. return new EdmComplexTypeReference(edmType as IEdmComplexType, isNullable);
  169. case EdmTypeKind.Entity:
  170. return new EdmEntityTypeReference(edmType as IEdmEntityType, isNullable);
  171. case EdmTypeKind.EntityReference:
  172. return new EdmEntityReferenceTypeReference(edmType as IEdmEntityReferenceType, isNullable);
  173. case EdmTypeKind.Enum:
  174. return new EdmEnumTypeReference(edmType as IEdmEnumType, isNullable);
  175. case EdmTypeKind.Primitive:
  176. return _coreModel.GetPrimitive((edmType as IEdmPrimitiveType).PrimitiveKind, isNullable);
  177. default:
  178. throw Error.NotSupported(SRResources.EdmTypeNotSupported, edmType.ToTraceString());
  179. }
  180. }
  181. public static IEdmCollectionType GetCollection(this IEdmEntityType entityType)
  182. {
  183. return new EdmCollectionType(new EdmEntityTypeReference(entityType, isNullable: false));
  184. }
  185. public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmModel)
  186. {
  187. return GetClrType(edmTypeReference, edmModel, _defaultAssemblyResolver);
  188. }
  189. public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmModel, IAssembliesResolver assembliesResolver)
  190. {
  191. if (edmTypeReference == null)
  192. {
  193. throw Error.ArgumentNull("edmTypeReference");
  194. }
  195. Type primitiveClrType = _builtInTypesMapping
  196. .Where(kvp => edmTypeReference.Definition.IsEquivalentTo(kvp.Value) && (!edmTypeReference.IsNullable || IsNullable(kvp.Key)))
  197. .Select(kvp => kvp.Key)
  198. .FirstOrDefault();
  199. if (primitiveClrType != null)
  200. {
  201. return primitiveClrType;
  202. }
  203. else
  204. {
  205. return GetClrType(edmTypeReference.Definition, edmModel, assembliesResolver);
  206. }
  207. }
  208. public static Type GetClrType(IEdmType edmType, IEdmModel edmModel)
  209. {
  210. return GetClrType(edmType, edmModel, _defaultAssemblyResolver);
  211. }
  212. public static Type GetClrType(IEdmType edmType, IEdmModel edmModel, IAssembliesResolver assembliesResolver)
  213. {
  214. IEdmSchemaType edmSchemaType = edmType as IEdmSchemaType;
  215. Contract.Assert(edmSchemaType != null);
  216. ClrTypeAnnotation annotation = edmModel.GetAnnotationValue<ClrTypeAnnotation>(edmSchemaType);
  217. if (annotation != null)
  218. {
  219. return annotation.ClrType;
  220. }
  221. string typeName = edmSchemaType.FullName();
  222. IEnumerable<Type> matchingTypes = GetMatchingTypes(typeName, assembliesResolver);
  223. if (matchingTypes.Count() > 1)
  224. {
  225. throw Error.Argument("edmTypeReference", SRResources.MultipleMatchingClrTypesForEdmType,
  226. typeName, String.Join(",", matchingTypes.Select(type => type.AssemblyQualifiedName)));
  227. }
  228. edmModel.SetAnnotationValue<ClrTypeAnnotation>(edmSchemaType, new ClrTypeAnnotation(matchingTypes.SingleOrDefault()));
  229. return matchingTypes.SingleOrDefault();
  230. }
  231. public static bool IsNonFilterable(IEdmProperty edmProperty, IEdmModel edmModel)
  232. {
  233. QueryableRestrictionsAnnotation annotation = GetPropertyRestrictions(edmProperty, edmModel);
  234. return annotation == null ? false : annotation.Restrictions.NonFilterable;
  235. }
  236. public static bool IsUnsortable(IEdmProperty edmProperty, IEdmModel edmModel)
  237. {
  238. QueryableRestrictionsAnnotation annotation = GetPropertyRestrictions(edmProperty, edmModel);
  239. return annotation == null ? false : annotation.Restrictions.Unsortable;
  240. }
  241. public static bool IsNotNavigable(IEdmProperty edmProperty, IEdmModel edmModel)
  242. {
  243. QueryableRestrictionsAnnotation annotation = GetPropertyRestrictions(edmProperty, edmModel);
  244. return annotation == null ? false : annotation.Restrictions.NotNavigable;
  245. }
  246. public static bool IsNotExpandable(IEdmProperty edmProperty, IEdmModel edmModel)
  247. {
  248. QueryableRestrictionsAnnotation annotation = GetPropertyRestrictions(edmProperty, edmModel);
  249. return annotation == null ? false : annotation.Restrictions.NotExpandable;
  250. }
  251. private static QueryableRestrictionsAnnotation GetPropertyRestrictions(IEdmProperty edmProperty, IEdmModel edmModel)
  252. {
  253. Contract.Assert(edmProperty != null);
  254. Contract.Assert(edmModel != null);
  255. return edmModel.GetAnnotationValue<QueryableRestrictionsAnnotation>(edmProperty);
  256. }
  257. public static string GetClrPropertyName(IEdmProperty edmProperty, IEdmModel edmModel)
  258. {
  259. if (edmProperty == null)
  260. {
  261. throw Error.ArgumentNull("edmProperty");
  262. }
  263. if (edmModel == null)
  264. {
  265. throw Error.ArgumentNull("edmModel");
  266. }
  267. string propertyName = edmProperty.Name;
  268. ClrPropertyInfoAnnotation annotation = edmModel.GetAnnotationValue<ClrPropertyInfoAnnotation>(edmProperty);
  269. if (annotation != null)
  270. {
  271. PropertyInfo propertyInfo = annotation.ClrPropertyInfo;
  272. if (propertyInfo != null)
  273. {
  274. propertyName = propertyInfo.Name;
  275. }
  276. }
  277. return propertyName;
  278. }
  279. public static PropertyInfo GetDynamicPropertyDictionary(IEdmStructuredType edmType, IEdmModel edmModel)
  280. {
  281. if (edmType == null)
  282. {
  283. throw Error.ArgumentNull("edmType");
  284. }
  285. if (edmModel == null)
  286. {
  287. throw Error.ArgumentNull("edmModel");
  288. }
  289. DynamicPropertyDictionaryAnnotation annotation =
  290. edmModel.GetAnnotationValue<DynamicPropertyDictionaryAnnotation>(edmType);
  291. if (annotation != null)
  292. {
  293. return annotation.PropertyInfo;
  294. }
  295. return null;
  296. }
  297. public static IEdmPrimitiveType GetEdmPrimitiveTypeOrNull(Type clrType)
  298. {
  299. IEdmPrimitiveType primitiveType;
  300. return _builtInTypesMapping.TryGetValue(clrType, out primitiveType) ? primitiveType : null;
  301. }
  302. public static IEdmPrimitiveTypeReference GetEdmPrimitiveTypeReferenceOrNull(Type clrType)
  303. {
  304. IEdmPrimitiveType primitiveType = GetEdmPrimitiveTypeOrNull(clrType);
  305. return primitiveType != null ? _coreModel.GetPrimitive(primitiveType.PrimitiveKind, IsNullable(clrType)) : null;
  306. }
  307. // figures out if the given clr type is nonstandard edm primitive like uint, ushort, char[] etc.
  308. // and returns the corresponding clr type to which we map like uint => long.
  309. public static Type IsNonstandardEdmPrimitive(Type type, out bool isNonstandardEdmPrimitive)
  310. {
  311. IEdmPrimitiveTypeReference edmType = GetEdmPrimitiveTypeReferenceOrNull(type);
  312. if (edmType == null)
  313. {
  314. isNonstandardEdmPrimitive = false;
  315. return type;
  316. }
  317. Type reverseLookupClrType = GetClrType(edmType, EdmCoreModel.Instance);
  318. isNonstandardEdmPrimitive = (type != reverseLookupClrType);
  319. return reverseLookupClrType;
  320. }
  321. // Mangle the invalid EDM literal Type.FullName (System.Collections.Generic.IEnumerable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]])
  322. // to a valid EDM literal (the C# type name IEnumerable<int>).
  323. public static string EdmName(this Type clrType)
  324. {
  325. // We cannot use just Type.Name here as it doesn't work for generic types.
  326. return MangleClrTypeName(clrType);
  327. }
  328. public static string EdmFullName(this Type clrType)
  329. {
  330. return String.Format(CultureInfo.InvariantCulture, "{0}.{1}", clrType.Namespace, clrType.EdmName());
  331. }
  332. public static IEnumerable<IEdmStructuralProperty> GetConcurrencyProperties(this IEdmEntityType type)
  333. {
  334. return type.StructuralProperties()
  335. .Where(s => s.ConcurrencyMode == EdmConcurrencyMode.Fixed && s.Type.IsPrimitive());
  336. }
  337. private static IEdmPrimitiveType GetPrimitiveType(EdmPrimitiveTypeKind primitiveKind)
  338. {
  339. return _coreModel.GetPrimitiveType(primitiveKind);
  340. }
  341. public static bool IsNullable(Type type)
  342. {
  343. return !type.IsValueType || Nullable.GetUnderlyingType(type) != null;
  344. }
  345. private static bool IsSelectExpandWrapper(Type type, out Type entityType)
  346. {
  347. if (type == null)
  348. {
  349. entityType = null;
  350. return false;
  351. }
  352. if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(SelectExpandWrapper<>))
  353. {
  354. entityType = type.GetGenericArguments()[0];
  355. return true;
  356. }
  357. return IsSelectExpandWrapper(type.BaseType, out entityType);
  358. }
  359. private static Type ExtractGenericInterface(Type queryType, Type interfaceType)
  360. {
  361. Func<Type, bool> matchesInterface = t => t.IsGenericType && t.GetGenericTypeDefinition() == interfaceType;
  362. return matchesInterface(queryType) ? queryType : queryType.GetInterfaces().FirstOrDefault(matchesInterface);
  363. }
  364. private static IEnumerable<Type> GetMatchingTypes(string edmFullName, IAssembliesResolver assembliesResolver)
  365. {
  366. return TypeHelper.GetLoadedTypes(assembliesResolver).Where(t => t.IsPublic && t.EdmFullName() == edmFullName);
  367. }
  368. // TODO (workitem 336): Support nested types and anonymous types.
  369. private static string MangleClrTypeName(Type type)
  370. {
  371. Contract.Assert(type != null);
  372. if (!type.IsGenericType)
  373. {
  374. return type.Name;
  375. }
  376. else
  377. {
  378. return String.Format(
  379. CultureInfo.InvariantCulture,
  380. "{0}Of{1}",
  381. type.Name.Replace('`', '_'),
  382. String.Join("_", type.GetGenericArguments().Select(t => MangleClrTypeName(t))));
  383. }
  384. }
  385. }
  386. }