ExtensibleUtil.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using System;
  2. using System.Collections;
  3. #if !NO_GENERICS
  4. using System.Collections.Generic;
  5. #endif
  6. using System.IO;
  7. using ProtoBuf.Meta;
  8. namespace ProtoBuf
  9. {
  10. /// <summary>
  11. /// This class acts as an internal wrapper allowing us to do a dynamic
  12. /// methodinfo invoke; an't put into Serializer as don't want on public
  13. /// API; can't put into Serializer&lt;T&gt; since we need to invoke
  14. /// accross classes, which isn't allowed in Silverlight)
  15. /// </summary>
  16. internal
  17. #if FX11
  18. sealed
  19. #else
  20. static
  21. #endif
  22. class ExtensibleUtil
  23. {
  24. #if FX11
  25. private ExtensibleUtil() { } // not a static class for C# 1.2 reasons
  26. #endif
  27. #if !NO_RUNTIME && !NO_GENERICS
  28. /// <summary>
  29. /// All this does is call GetExtendedValuesTyped with the correct type for "instance";
  30. /// this ensures that we don't get issues with subclasses declaring conflicting types -
  31. /// the caller must respect the fields defined for the type they pass in.
  32. /// </summary>
  33. internal static IEnumerable<TValue> GetExtendedValues<TValue>(IExtensible instance, int tag, DataFormat format, bool singleton, bool allowDefinedTag)
  34. {
  35. foreach (TValue value in GetExtendedValues(RuntimeTypeModel.Default, typeof(TValue), instance, tag, format, singleton, allowDefinedTag))
  36. {
  37. yield return value;
  38. }
  39. }
  40. #endif
  41. /// <summary>
  42. /// All this does is call GetExtendedValuesTyped with the correct type for "instance";
  43. /// this ensures that we don't get issues with subclasses declaring conflicting types -
  44. /// the caller must respect the fields defined for the type they pass in.
  45. /// </summary>
  46. internal static IEnumerable GetExtendedValues(TypeModel model, Type type, IExtensible instance, int tag, DataFormat format, bool singleton, bool allowDefinedTag)
  47. {
  48. #if FEAT_IKVM
  49. throw new NotSupportedException();
  50. #else
  51. if (instance == null) throw new ArgumentNullException("instance");
  52. if (tag <= 0) throw new ArgumentOutOfRangeException("tag");
  53. IExtension extn = instance.GetExtensionObject(false);
  54. if (extn == null)
  55. {
  56. #if FX11
  57. return new object[0];
  58. #else
  59. yield break;
  60. #endif
  61. }
  62. #if FX11
  63. BasicList result = new BasicList();
  64. #endif
  65. Stream stream = extn.BeginQuery();
  66. object value = null;
  67. ProtoReader reader = null;
  68. try {
  69. SerializationContext ctx = new SerializationContext();
  70. reader = ProtoReader.Create(stream, model, ctx, ProtoReader.TO_EOF);
  71. while (model.TryDeserializeAuxiliaryType(reader, format, tag, type, ref value, true, false, false, false) && value != null)
  72. {
  73. if (!singleton)
  74. {
  75. #if FX11
  76. result.Add(value);
  77. #else
  78. yield return value;
  79. #endif
  80. value = null; // fresh item each time
  81. }
  82. }
  83. if (singleton && value != null)
  84. {
  85. #if FX11
  86. result.Add(value);
  87. #else
  88. yield return value;
  89. #endif
  90. }
  91. #if FX11
  92. object[] resultArr = new object[result.Count];
  93. result.CopyTo(resultArr, 0);
  94. return resultArr;
  95. #endif
  96. } finally {
  97. ProtoReader.Recycle(reader);
  98. extn.EndQuery(stream);
  99. }
  100. #endif
  101. }
  102. internal static void AppendExtendValue(TypeModel model, IExtensible instance, int tag, DataFormat format, object value)
  103. {
  104. #if FEAT_IKVM
  105. throw new NotSupportedException();
  106. #else
  107. if(instance == null) throw new ArgumentNullException("instance");
  108. if(value == null) throw new ArgumentNullException("value");
  109. // TODO
  110. //model.CheckTagNotInUse(tag);
  111. // obtain the extension object and prepare to write
  112. IExtension extn = instance.GetExtensionObject(true);
  113. if (extn == null) throw new InvalidOperationException("No extension object available; appended data would be lost.");
  114. bool commit = false;
  115. Stream stream = extn.BeginAppend();
  116. try {
  117. using(ProtoWriter writer = new ProtoWriter(stream, model, null)) {
  118. model.TrySerializeAuxiliaryType(writer, null, format, tag, value, false);
  119. writer.Close();
  120. }
  121. commit = true;
  122. }
  123. finally {
  124. extn.EndAppend(stream, commit);
  125. }
  126. #endif
  127. }
  128. //#if !NO_GENERICS
  129. // /// <summary>
  130. // /// Stores the given value into the instance's stream; the serializer
  131. // /// is inferred from TValue and format.
  132. // /// </summary>
  133. // /// <remarks>Needs to be public to be callable thru reflection in Silverlight</remarks>
  134. // public static void AppendExtendValueTyped<TSource, TValue>(
  135. // TypeModel model, TSource instance, int tag, DataFormat format, TValue value)
  136. // where TSource : class, IExtensible
  137. // {
  138. // AppendExtendValue(model, instance, tag, format, value);
  139. // }
  140. //#endif
  141. }
  142. }