GeneratedMessage.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // http://github.com/jskeet/dotnet-protobufs/
  5. // Original C++/Java/Python code:
  6. // http://code.google.com/p/protobuf/
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. //
  12. // * Redistributions of source code must retain the above copyright
  13. // notice, this list of conditions and the following disclaimer.
  14. // * Redistributions in binary form must reproduce the above
  15. // copyright notice, this list of conditions and the following disclaimer
  16. // in the documentation and/or other materials provided with the
  17. // distribution.
  18. // * Neither the name of Google Inc. nor the names of its
  19. // contributors may be used to endorse or promote products derived from
  20. // this software without specific prior written permission.
  21. //
  22. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  26. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  27. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  28. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. #endregion
  34. using System;
  35. using System.Collections;
  36. using System.Collections.Generic;
  37. using System.IO;
  38. using System.Xml;
  39. using Google.ProtocolBuffers.Collections;
  40. using Google.ProtocolBuffers.Descriptors;
  41. using Google.ProtocolBuffers.FieldAccess;
  42. namespace Google.ProtocolBuffers
  43. {
  44. /// <summary>
  45. /// All generated protocol message classes extend this class. It implements
  46. /// most of the IMessage interface using reflection. Users
  47. /// can ignore this class as an implementation detail.
  48. /// </summary>
  49. public abstract partial class GeneratedMessage<TMessage, TBuilder> : AbstractMessage<TMessage, TBuilder>
  50. where TMessage : GeneratedMessage<TMessage, TBuilder>
  51. where TBuilder : GeneratedBuilder<TMessage, TBuilder>, new()
  52. {
  53. private UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
  54. /// <summary>
  55. /// Returns the message as a TMessage.
  56. /// </summary>
  57. protected abstract TMessage ThisMessage { get; }
  58. internal FieldAccessorTable<TMessage, TBuilder> FieldAccessorsFromBuilder
  59. {
  60. get { return InternalFieldAccessors; }
  61. }
  62. protected abstract FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors { get; }
  63. public override MessageDescriptor DescriptorForType
  64. {
  65. get { return InternalFieldAccessors.Descriptor; }
  66. }
  67. internal IDictionary<FieldDescriptor, Object> GetMutableFieldMap()
  68. {
  69. // Use a SortedDictionary so we'll end up serializing fields in order
  70. var ret = new SortedDictionary<FieldDescriptor, object>();
  71. MessageDescriptor descriptor = DescriptorForType;
  72. foreach (FieldDescriptor field in descriptor.Fields)
  73. {
  74. IFieldAccessor<TMessage, TBuilder> accessor = InternalFieldAccessors[field];
  75. if (field.IsRepeated)
  76. {
  77. if (accessor.GetRepeatedCount(ThisMessage) != 0)
  78. {
  79. ret[field] = accessor.GetValue(ThisMessage);
  80. }
  81. }
  82. else if (HasField(field))
  83. {
  84. ret[field] = accessor.GetValue(ThisMessage);
  85. }
  86. }
  87. return ret;
  88. }
  89. public override bool IsInitialized
  90. {
  91. get
  92. {
  93. foreach (FieldDescriptor field in DescriptorForType.Fields)
  94. {
  95. // Check that all required fields are present.
  96. if (field.IsRequired && !HasField(field))
  97. {
  98. return false;
  99. }
  100. // Check that embedded messages are initialized.
  101. // This code is similar to that in AbstractMessage, but we don't
  102. // fetch all the field values - just the ones we need to.
  103. if (field.MappedType == MappedType.Message)
  104. {
  105. if (field.IsRepeated)
  106. {
  107. // We know it's an IList<T>, but not the exact type - so
  108. // IEnumerable is the best we can do. (C# generics aren't covariant yet.)
  109. foreach (IMessageLite element in (IEnumerable) this[field])
  110. {
  111. if (!element.IsInitialized)
  112. {
  113. return false;
  114. }
  115. }
  116. }
  117. else
  118. {
  119. if (HasField(field) && !((IMessageLite) this[field]).IsInitialized)
  120. {
  121. return false;
  122. }
  123. }
  124. }
  125. }
  126. return true;
  127. }
  128. }
  129. public override IDictionary<FieldDescriptor, object> AllFields
  130. {
  131. get { return Dictionaries.AsReadOnly(GetMutableFieldMap()); }
  132. }
  133. public override bool HasOneof(OneofDescriptor oneof)
  134. {
  135. return InternalFieldAccessors.Oneof(oneof).Has(ThisMessage);
  136. }
  137. public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof)
  138. {
  139. return InternalFieldAccessors.Oneof(oneof).GetOneofFieldDescriptor(ThisMessage);
  140. }
  141. public override bool HasField(FieldDescriptor field)
  142. {
  143. return InternalFieldAccessors[field].Has(ThisMessage);
  144. }
  145. public override int GetRepeatedFieldCount(FieldDescriptor field)
  146. {
  147. return InternalFieldAccessors[field].GetRepeatedCount(ThisMessage);
  148. }
  149. public override object this[FieldDescriptor field, int index]
  150. {
  151. get { return InternalFieldAccessors[field].GetRepeatedValue(ThisMessage, index); }
  152. }
  153. public override object this[FieldDescriptor field]
  154. {
  155. get { return InternalFieldAccessors[field].GetValue(ThisMessage); }
  156. }
  157. public override UnknownFieldSet UnknownFields
  158. {
  159. get { return unknownFields; }
  160. }
  161. /// <summary>
  162. /// Replaces the set of unknown fields for this message. This should
  163. /// only be used before a message is built, by the builder. (In the
  164. /// Java code it is private, but the builder is nested so has access
  165. /// to it.)
  166. /// </summary>
  167. internal void SetUnknownFields(UnknownFieldSet fieldSet)
  168. {
  169. unknownFields = fieldSet;
  170. }
  171. }
  172. }