Helpers.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. 
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. #if FEAT_IKVM
  6. using Type = IKVM.Reflection.Type;
  7. using IKVM.Reflection;
  8. #else
  9. using System.Reflection;
  10. #endif
  11. namespace ProtoBuf
  12. {
  13. /// <summary>
  14. /// Not all frameworks are created equal (fx1.1 vs fx2.0,
  15. /// micro-framework, compact-framework,
  16. /// silverlight, etc). This class simply wraps up a few things that would
  17. /// otherwise make the real code unnecessarily messy, providing fallback
  18. /// implementations if necessary.
  19. /// </summary>
  20. internal sealed class Helpers
  21. {
  22. private Helpers() { }
  23. public static System.Text.StringBuilder AppendLine(System.Text.StringBuilder builder)
  24. {
  25. #if CF2
  26. return builder.Append("\r\n");
  27. #elif FX11
  28. return builder.Append(Environment.NewLine);
  29. #else
  30. return builder.AppendLine();
  31. #endif
  32. }
  33. public static bool IsNullOrEmpty(string value)
  34. { // yes, FX11 lacks this!
  35. return value == null || value.Length == 0;
  36. }
  37. [System.Diagnostics.Conditional("DEBUG")]
  38. public static void DebugWriteLine(string message, object obj)
  39. {
  40. #if DEBUG
  41. string suffix;
  42. try
  43. {
  44. suffix = obj == null ? "(null)" : obj.ToString();
  45. }
  46. catch
  47. {
  48. suffix = "(exception)";
  49. }
  50. DebugWriteLine(message + ": " + suffix);
  51. #endif
  52. }
  53. [System.Diagnostics.Conditional("DEBUG")]
  54. public static void DebugWriteLine(string message)
  55. {
  56. #if DEBUG
  57. #if MF
  58. Microsoft.SPOT.Debug.Print(message);
  59. #else
  60. System.Diagnostics.Debug.WriteLine(message);
  61. #endif
  62. #endif
  63. }
  64. [System.Diagnostics.Conditional("TRACE")]
  65. public static void TraceWriteLine(string message)
  66. {
  67. #if TRACE
  68. #if MF
  69. Microsoft.SPOT.Trace.Print(message);
  70. #elif SILVERLIGHT || MONODROID || CF2 || WINRT || IOS || PORTABLE || COREFX
  71. System.Diagnostics.Debug.WriteLine(message);
  72. #else
  73. System.Diagnostics.Trace.WriteLine(message);
  74. #endif
  75. #endif
  76. }
  77. [System.Diagnostics.Conditional("DEBUG")]
  78. public static void DebugAssert(bool condition, string message)
  79. {
  80. #if DEBUG
  81. if (!condition)
  82. {
  83. #if MF
  84. Microsoft.SPOT.Debug.Assert(false, message);
  85. #else
  86. System.Diagnostics.Debug.Assert(false, message);
  87. }
  88. #endif
  89. #endif
  90. }
  91. [System.Diagnostics.Conditional("DEBUG")]
  92. public static void DebugAssert(bool condition, string message, params object[] args)
  93. {
  94. #if DEBUG
  95. if (!condition) DebugAssert(false, string.Format(message, args));
  96. #endif
  97. }
  98. [System.Diagnostics.Conditional("DEBUG")]
  99. public static void DebugAssert(bool condition)
  100. {
  101. #if DEBUG
  102. #if MF
  103. Microsoft.SPOT.Debug.Assert(condition);
  104. #else
  105. if(!condition && System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();
  106. System.Diagnostics.Debug.Assert(condition);
  107. #endif
  108. #endif
  109. }
  110. #if !NO_RUNTIME
  111. public static void Sort(int[] keys, object[] values)
  112. {
  113. // bubble-sort; it'll work on MF, has small code,
  114. // and works well-enough for our sizes. This approach
  115. // also allows us to do `int` compares without having
  116. // to go via IComparable etc, so win:win
  117. bool swapped;
  118. do {
  119. swapped = false;
  120. for (int i = 1; i < keys.Length; i++) {
  121. if (keys[i - 1] > keys[i]) {
  122. int tmpKey = keys[i];
  123. keys[i] = keys[i - 1];
  124. keys[i - 1] = tmpKey;
  125. object tmpValue = values[i];
  126. values[i] = values[i - 1];
  127. values[i - 1] = tmpValue;
  128. swapped = true;
  129. }
  130. }
  131. } while (swapped);
  132. }
  133. #endif
  134. public static void BlockCopy(byte[] from, int fromIndex, byte[] to, int toIndex, int count)
  135. {
  136. #if MF || WINRT
  137. Array.Copy(from, fromIndex, to, toIndex, count);
  138. #else
  139. Buffer.BlockCopy(from, fromIndex, to, toIndex, count);
  140. #endif
  141. }
  142. public static bool IsInfinity(float value)
  143. {
  144. #if MF
  145. const float inf = (float)1.0 / (float)0.0, minf = (float)-1.0F / (float)0.0;
  146. return value == inf || value == minf;
  147. #else
  148. return float.IsInfinity(value);
  149. #endif
  150. }
  151. #if WINRT || COREFX
  152. internal static MemberInfo GetInstanceMember(TypeInfo declaringType, string name)
  153. {
  154. var members = declaringType.AsType().GetMember(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  155. switch(members.Length)
  156. {
  157. case 0: return null;
  158. case 1: return members[0];
  159. default: throw new AmbiguousMatchException(name);
  160. }
  161. }
  162. internal static MethodInfo GetInstanceMethod(Type declaringType, string name)
  163. {
  164. foreach (MethodInfo method in declaringType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
  165. {
  166. if (method.Name == name) return method;
  167. }
  168. return null;
  169. }
  170. internal static MethodInfo GetInstanceMethod(TypeInfo declaringType, string name)
  171. {
  172. return GetInstanceMethod(declaringType.AsType(), name); ;
  173. }
  174. internal static MethodInfo GetStaticMethod(Type declaringType, string name)
  175. {
  176. foreach (MethodInfo method in declaringType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
  177. {
  178. if (method.Name == name) return method;
  179. }
  180. return null;
  181. }
  182. internal static MethodInfo GetStaticMethod(TypeInfo declaringType, string name)
  183. {
  184. return GetStaticMethod(declaringType.AsType(), name);
  185. }
  186. internal static MethodInfo GetStaticMethod(Type declaringType, string name, Type[] parameterTypes)
  187. {
  188. foreach(MethodInfo method in declaringType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
  189. {
  190. if (method.Name == name && IsMatch(method.GetParameters(), parameterTypes)) return method;
  191. }
  192. return null;
  193. }
  194. internal static MethodInfo GetInstanceMethod(Type declaringType, string name, Type[] parameterTypes)
  195. {
  196. foreach (MethodInfo method in declaringType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
  197. {
  198. if (method.Name == name && IsMatch(method.GetParameters(), parameterTypes)) return method;
  199. }
  200. return null;
  201. }
  202. internal static MethodInfo GetInstanceMethod(TypeInfo declaringType, string name, Type[] types)
  203. {
  204. return GetInstanceMethod(declaringType.AsType(), name, types);
  205. }
  206. #else
  207. internal static MethodInfo GetInstanceMethod(Type declaringType, string name)
  208. {
  209. return declaringType.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  210. }
  211. internal static MethodInfo GetStaticMethod(Type declaringType, string name)
  212. {
  213. return declaringType.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
  214. }
  215. internal static MethodInfo GetStaticMethod(Type declaringType, string name, Type[] parameterTypes)
  216. {
  217. return declaringType.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null);
  218. }
  219. internal static MethodInfo GetInstanceMethod(Type declaringType, string name, Type[] types)
  220. {
  221. if(types == null) types = EmptyTypes;
  222. #if PORTABLE || COREFX
  223. MethodInfo method = declaringType.GetMethod(name, types);
  224. if (method != null && method.IsStatic) method = null;
  225. return method;
  226. #else
  227. return declaringType.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
  228. null, types, null);
  229. #endif
  230. }
  231. #endif
  232. internal static bool IsSubclassOf(Type type, Type baseClass)
  233. {
  234. #if WINRT || COREFX
  235. return type.GetTypeInfo().IsSubclassOf(baseClass);
  236. #else
  237. return type.IsSubclassOf(baseClass);
  238. #endif
  239. }
  240. public static bool IsInfinity(double value)
  241. {
  242. #if MF
  243. const double inf = (double)1.0 / (double)0.0, minf = (double)-1.0F / (double)0.0;
  244. return value == inf || value == minf;
  245. #else
  246. return double.IsInfinity(value);
  247. #endif
  248. }
  249. public readonly static Type[] EmptyTypes =
  250. #if PORTABLE || WINRT || CF2 || CF35
  251. new Type[0];
  252. #else
  253. Type.EmptyTypes;
  254. #endif
  255. #if WINRT || COREFX
  256. private static readonly Type[] knownTypes = new Type[] {
  257. typeof(bool), typeof(char), typeof(sbyte), typeof(byte),
  258. typeof(short), typeof(ushort), typeof(int), typeof(uint),
  259. typeof(long), typeof(ulong), typeof(float), typeof(double),
  260. typeof(decimal), typeof(string),
  261. typeof(DateTime), typeof(TimeSpan), typeof(Guid), typeof(Uri),
  262. typeof(byte[]), typeof(System.Type)};
  263. private static readonly ProtoTypeCode[] knownCodes = new ProtoTypeCode[] {
  264. ProtoTypeCode.Boolean, ProtoTypeCode.Char, ProtoTypeCode.SByte, ProtoTypeCode.Byte,
  265. ProtoTypeCode.Int16, ProtoTypeCode.UInt16, ProtoTypeCode.Int32, ProtoTypeCode.UInt32,
  266. ProtoTypeCode.Int64, ProtoTypeCode.UInt64, ProtoTypeCode.Single, ProtoTypeCode.Double,
  267. ProtoTypeCode.Decimal, ProtoTypeCode.String,
  268. ProtoTypeCode.DateTime, ProtoTypeCode.TimeSpan, ProtoTypeCode.Guid, ProtoTypeCode.Uri,
  269. ProtoTypeCode.ByteArray, ProtoTypeCode.Type
  270. };
  271. #endif
  272. #if FEAT_IKVM
  273. public static ProtoTypeCode GetTypeCode(IKVM.Reflection.Type type)
  274. {
  275. TypeCode code = IKVM.Reflection.Type.GetTypeCode(type);
  276. switch (code)
  277. {
  278. case TypeCode.Empty:
  279. case TypeCode.Boolean:
  280. case TypeCode.Char:
  281. case TypeCode.SByte:
  282. case TypeCode.Byte:
  283. case TypeCode.Int16:
  284. case TypeCode.UInt16:
  285. case TypeCode.Int32:
  286. case TypeCode.UInt32:
  287. case TypeCode.Int64:
  288. case TypeCode.UInt64:
  289. case TypeCode.Single:
  290. case TypeCode.Double:
  291. case TypeCode.Decimal:
  292. case TypeCode.DateTime:
  293. case TypeCode.String:
  294. return (ProtoTypeCode)code;
  295. }
  296. switch(type.FullName)
  297. {
  298. case "System.TimeSpan": return ProtoTypeCode.TimeSpan;
  299. case "System.Guid": return ProtoTypeCode.Guid;
  300. case "System.Uri": return ProtoTypeCode.Uri;
  301. case "System.Byte[]": return ProtoTypeCode.ByteArray;
  302. case "System.Type": return ProtoTypeCode.Type;
  303. }
  304. return ProtoTypeCode.Unknown;
  305. }
  306. #endif
  307. public static ProtoTypeCode GetTypeCode(System.Type type)
  308. {
  309. #if WINRT || COREFX
  310. if(IsEnum(type))
  311. {
  312. type = Enum.GetUnderlyingType(type);
  313. }
  314. int idx = Array.IndexOf<Type>(knownTypes, type);
  315. if (idx >= 0) return knownCodes[idx];
  316. return type == null ? ProtoTypeCode.Empty : ProtoTypeCode.Unknown;
  317. #else
  318. TypeCode code = System.Type.GetTypeCode(type);
  319. switch (code)
  320. {
  321. case TypeCode.Empty:
  322. case TypeCode.Boolean:
  323. case TypeCode.Char:
  324. case TypeCode.SByte:
  325. case TypeCode.Byte:
  326. case TypeCode.Int16:
  327. case TypeCode.UInt16:
  328. case TypeCode.Int32:
  329. case TypeCode.UInt32:
  330. case TypeCode.Int64:
  331. case TypeCode.UInt64:
  332. case TypeCode.Single:
  333. case TypeCode.Double:
  334. case TypeCode.Decimal:
  335. case TypeCode.DateTime:
  336. case TypeCode.String:
  337. return (ProtoTypeCode)code;
  338. }
  339. if (type == typeof(TimeSpan)) return ProtoTypeCode.TimeSpan;
  340. if (type == typeof(Guid)) return ProtoTypeCode.Guid;
  341. if (type == typeof(Uri)) return ProtoTypeCode.Uri;
  342. #if PORTABLE
  343. // In PCLs, the Uri type may not match (WinRT uses Internal/Uri, .Net uses System/Uri), so match on the full name instead
  344. if (type.FullName == typeof(Uri).FullName) return ProtoTypeCode.Uri;
  345. #endif
  346. if (type == typeof(byte[])) return ProtoTypeCode.ByteArray;
  347. if (type == typeof(System.Type)) return ProtoTypeCode.Type;
  348. return ProtoTypeCode.Unknown;
  349. #endif
  350. }
  351. #if FEAT_IKVM
  352. internal static IKVM.Reflection.Type GetUnderlyingType(IKVM.Reflection.Type type)
  353. {
  354. if (type.IsValueType && type.IsGenericType && type.GetGenericTypeDefinition().FullName == "System.Nullable`1")
  355. {
  356. return type.GetGenericArguments()[0];
  357. }
  358. return null;
  359. }
  360. #endif
  361. internal static System.Type GetUnderlyingType(System.Type type)
  362. {
  363. #if NO_GENERICS
  364. return null; // never a Nullable<T>, so always returns null
  365. #else
  366. return Nullable.GetUnderlyingType(type);
  367. #endif
  368. }
  369. internal static bool IsValueType(Type type)
  370. {
  371. #if WINRT || COREFX
  372. return type.GetTypeInfo().IsValueType;
  373. #else
  374. return type.IsValueType;
  375. #endif
  376. }
  377. internal static bool IsSealed(Type type)
  378. {
  379. #if WINRT || COREFX
  380. return type.GetTypeInfo().IsSealed;
  381. #else
  382. return type.IsSealed;
  383. #endif
  384. }
  385. internal static bool IsClass(Type type)
  386. {
  387. #if WINRT || COREFX
  388. return type.GetTypeInfo().IsClass;
  389. #else
  390. return type.IsClass;
  391. #endif
  392. }
  393. internal static bool IsEnum(Type type)
  394. {
  395. #if WINRT || COREFX
  396. return type.GetTypeInfo().IsEnum;
  397. #else
  398. return type.IsEnum;
  399. #endif
  400. }
  401. internal static MethodInfo GetGetMethod(PropertyInfo property, bool nonPublic, bool allowInternal)
  402. {
  403. if (property == null) return null;
  404. #if WINRT || COREFX
  405. MethodInfo method = property.GetMethod;
  406. if (!nonPublic && method != null && !method.IsPublic) method = null;
  407. return method;
  408. #else
  409. MethodInfo method = property.GetGetMethod(nonPublic);
  410. if (method == null && !nonPublic && allowInternal)
  411. { // could be "internal" or "protected internal"; look for a non-public, then back-check
  412. method = property.GetGetMethod(true);
  413. if (method == null && !(method.IsAssembly || method.IsFamilyOrAssembly))
  414. {
  415. method = null;
  416. }
  417. }
  418. return method;
  419. #endif
  420. }
  421. internal static MethodInfo GetSetMethod(PropertyInfo property, bool nonPublic, bool allowInternal)
  422. {
  423. if (property == null) return null;
  424. #if WINRT || COREFX
  425. MethodInfo method = property.SetMethod;
  426. if (!nonPublic && method != null && !method.IsPublic) method = null;
  427. return method;
  428. #else
  429. MethodInfo method = property.GetSetMethod(nonPublic);
  430. if (method == null && !nonPublic && allowInternal)
  431. { // could be "internal" or "protected internal"; look for a non-public, then back-check
  432. method = property.GetGetMethod(true);
  433. if (method == null && !(method.IsAssembly || method.IsFamilyOrAssembly))
  434. {
  435. method = null;
  436. }
  437. }
  438. return method;
  439. #endif
  440. }
  441. #if FEAT_IKVM
  442. internal static bool IsMatch(IKVM.Reflection.ParameterInfo[] parameters, IKVM.Reflection.Type[] parameterTypes)
  443. {
  444. if (parameterTypes == null) parameterTypes = Helpers.EmptyTypes;
  445. if (parameters.Length != parameterTypes.Length) return false;
  446. for (int i = 0; i < parameters.Length; i++)
  447. {
  448. if (parameters[i].ParameterType != parameterTypes[i]) return false;
  449. }
  450. return true;
  451. }
  452. #endif
  453. #if WINRT || COREFX
  454. private static bool IsMatch(ParameterInfo[] parameters, Type[] parameterTypes)
  455. {
  456. if (parameterTypes == null) parameterTypes = EmptyTypes;
  457. if (parameters.Length != parameterTypes.Length) return false;
  458. for (int i = 0; i < parameters.Length; i++)
  459. {
  460. if (parameters[i].ParameterType != parameterTypes[i]) return false;
  461. }
  462. return true;
  463. }
  464. internal static ConstructorInfo GetConstructor(Type type, Type[] parameterTypes, bool nonPublic)
  465. {
  466. return GetConstructor(type.GetTypeInfo(), parameterTypes, nonPublic);
  467. }
  468. internal static ConstructorInfo GetConstructor(TypeInfo type, Type[] parameterTypes, bool nonPublic)
  469. {
  470. foreach (ConstructorInfo ctor in type.DeclaredConstructors)
  471. {
  472. if (!nonPublic && !ctor.IsPublic) continue;
  473. if (IsMatch(ctor.GetParameters(), parameterTypes)) return ctor;
  474. }
  475. return null;
  476. }
  477. internal static ConstructorInfo[] GetConstructors(TypeInfo typeInfo, bool nonPublic)
  478. {
  479. if (nonPublic) return System.Linq.Enumerable.ToArray(typeInfo.DeclaredConstructors);
  480. return System.Linq.Enumerable.ToArray(
  481. System.Linq.Enumerable.Where(typeInfo.DeclaredConstructors, x => x.IsPublic));
  482. }
  483. internal static PropertyInfo GetProperty(Type type, string name, bool nonPublic)
  484. {
  485. return GetProperty(type.GetTypeInfo(), name, nonPublic);
  486. }
  487. internal static PropertyInfo GetProperty(TypeInfo type, string name, bool nonPublic)
  488. {
  489. return type.GetDeclaredProperty(name);
  490. }
  491. #else
  492. internal static ConstructorInfo GetConstructor(Type type, Type[] parameterTypes, bool nonPublic)
  493. {
  494. #if PORTABLE || COREFX
  495. // pretty sure this will only ever return public, but...
  496. ConstructorInfo ctor = type.GetConstructor(parameterTypes);
  497. return (ctor != null && (nonPublic || ctor.IsPublic)) ? ctor : null;
  498. #else
  499. return type.GetConstructor(
  500. nonPublic ? BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
  501. : BindingFlags.Instance | BindingFlags.Public,
  502. null, parameterTypes, null);
  503. #endif
  504. }
  505. internal static ConstructorInfo[] GetConstructors(Type type, bool nonPublic)
  506. {
  507. return type.GetConstructors(
  508. nonPublic ? BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
  509. : BindingFlags.Instance | BindingFlags.Public);
  510. }
  511. internal static PropertyInfo GetProperty(Type type, string name, bool nonPublic)
  512. {
  513. return type.GetProperty(name,
  514. nonPublic ? BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
  515. : BindingFlags.Instance | BindingFlags.Public);
  516. }
  517. #endif
  518. internal static object ParseEnum(Type type, string value)
  519. {
  520. #if FEAT_IKVM
  521. FieldInfo[] fields = type.GetFields();
  522. foreach (FieldInfo field in fields)
  523. {
  524. if (string.Equals(field.Name, value, StringComparison.OrdinalIgnoreCase)) return field.GetRawConstantValue();
  525. }
  526. throw new ArgumentException("Enum value could not be parsed: " + value + ", " + type.FullName);
  527. #else
  528. return Enum.Parse(type, value, true);
  529. #endif
  530. }
  531. internal static MemberInfo[] GetInstanceFieldsAndProperties(Type type, bool publicOnly)
  532. {
  533. #if WINRT
  534. System.Collections.Generic.List<MemberInfo> members = new System.Collections.Generic.List<MemberInfo>();
  535. foreach(FieldInfo field in type.GetRuntimeFields())
  536. {
  537. if(field.IsStatic) continue;
  538. if(field.IsPublic || !publicOnly) members.Add(field);
  539. }
  540. foreach(PropertyInfo prop in type.GetRuntimeProperties())
  541. {
  542. MethodInfo getter = Helpers.GetGetMethod(prop, true, true);
  543. if(getter == null || getter.IsStatic) continue;
  544. if(getter.IsPublic || !publicOnly) members.Add(prop);
  545. }
  546. return members.ToArray();
  547. #else
  548. BindingFlags flags = publicOnly ? BindingFlags.Public | BindingFlags.Instance : BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic;
  549. PropertyInfo[] props = type.GetProperties(flags);
  550. FieldInfo[] fields = type.GetFields(flags);
  551. MemberInfo[] members = new MemberInfo[fields.Length + props.Length];
  552. props.CopyTo(members, 0);
  553. fields.CopyTo(members, props.Length);
  554. return members;
  555. #endif
  556. }
  557. internal static Type GetMemberType(MemberInfo member)
  558. {
  559. #if WINRT || PORTABLE || COREFX
  560. PropertyInfo prop = member as PropertyInfo;
  561. if (prop != null) return prop.PropertyType;
  562. FieldInfo fld = member as FieldInfo;
  563. return fld == null ? null : fld.FieldType;
  564. #else
  565. switch(member.MemberType)
  566. {
  567. case MemberTypes.Field: return ((FieldInfo) member).FieldType;
  568. case MemberTypes.Property: return ((PropertyInfo) member).PropertyType;
  569. default: return null;
  570. }
  571. #endif
  572. }
  573. internal static bool IsAssignableFrom(Type target, Type type)
  574. {
  575. #if WINRT
  576. return target.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo());
  577. #else
  578. return target.IsAssignableFrom(type);
  579. #endif
  580. }
  581. internal static Assembly GetAssembly(Type type)
  582. {
  583. #if COREFX
  584. return type.GetTypeInfo().Assembly;
  585. #else
  586. return type.Assembly;
  587. #endif
  588. }
  589. internal static byte[] GetBuffer(MemoryStream ms)
  590. {
  591. #if COREFX
  592. ArraySegment<byte> segment;
  593. if(!ms.TryGetBuffer(out segment))
  594. {
  595. throw new InvalidOperationException("Unable to obtain underlying MemoryStream buffer");
  596. } else if(segment.Offset != 0)
  597. {
  598. throw new InvalidOperationException("Underlying MemoryStream buffer was not zero-offset");
  599. } else
  600. {
  601. return segment.Array;
  602. }
  603. #else
  604. return ms.GetBuffer();
  605. #endif
  606. }
  607. }
  608. /// <summary>
  609. /// Intended to be a direct map to regular TypeCode, but:
  610. /// - with missing types
  611. /// - existing on WinRT
  612. /// </summary>
  613. internal enum ProtoTypeCode
  614. {
  615. Empty = 0,
  616. Unknown = 1, // maps to TypeCode.Object
  617. Boolean = 3,
  618. Char = 4,
  619. SByte = 5,
  620. Byte = 6,
  621. Int16 = 7,
  622. UInt16 = 8,
  623. Int32 = 9,
  624. UInt32 = 10,
  625. Int64 = 11,
  626. UInt64 = 12,
  627. Single = 13,
  628. Double = 14,
  629. Decimal = 15,
  630. DateTime = 16,
  631. String = 18,
  632. // additions
  633. TimeSpan = 100,
  634. ByteArray = 101,
  635. Guid = 102,
  636. Uri = 103,
  637. Type = 104
  638. }
  639. }