aboutsummaryrefslogtreecommitdiff
path: root/csharp/ProtocolBuffers
diff options
context:
space:
mode:
authorJon Skeet <skeet@pobox.com>2008-08-14 20:35:22 +0100
committerJon Skeet <skeet@pobox.com>2008-08-14 20:35:22 +0100
commit3f9a6f211664021db368c4b4549793935315382a (patch)
tree2ecd2bd93f9db925f5f644a0d72ef34b65320158 /csharp/ProtocolBuffers
parent575083ae9c3ecb17e14ae29aa20b784940fcdfd1 (diff)
downloadprotobuf-3f9a6f211664021db368c4b4549793935315382a.tar.gz
protobuf-3f9a6f211664021db368c4b4549793935315382a.tar.bz2
protobuf-3f9a6f211664021db368c4b4549793935315382a.zip
Implemented GeneratedExtension, although list handling may be incorrect.
Diffstat (limited to 'csharp/ProtocolBuffers')
-rw-r--r--csharp/ProtocolBuffers/ExtendableMessage.cs8
-rw-r--r--csharp/ProtocolBuffers/ExtensionRegistry.cs2
-rw-r--r--csharp/ProtocolBuffers/GeneratedExtension.cs97
-rw-r--r--csharp/ProtocolBuffers/GeneratedExtensionBase.cs88
-rw-r--r--csharp/ProtocolBuffers/GeneratedRepeatException.cs42
-rw-r--r--csharp/ProtocolBuffers/GeneratedSingleExtension.cs26
-rw-r--r--csharp/ProtocolBuffers/ProtocolBuffers.csproj4
7 files changed, 164 insertions, 103 deletions
diff --git a/csharp/ProtocolBuffers/ExtendableMessage.cs b/csharp/ProtocolBuffers/ExtendableMessage.cs
index cf43b03b..872b15b6 100644
--- a/csharp/ProtocolBuffers/ExtendableMessage.cs
+++ b/csharp/ProtocolBuffers/ExtendableMessage.cs
@@ -15,21 +15,21 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Checks if a singular extension is present.
/// </summary>
- public bool HasExtension(GeneratedExtension<TMessage, TBuilder> extension) {
+ public bool HasExtension(GeneratedExtensionBase<TMessage, TBuilder> extension) {
return extensions.HasField(extension.Descriptor);
}
/// <summary>
/// Returns the number of elements in a repeated extension.
/// </summary>
- public int GetExtensionCount<TExtension>(GeneratedExtension<TMessage, IList<TExtension>> extension) {
+ public int GetExtensionCount<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension) {
return extensions.GetRepeatedFieldCount(extension.Descriptor);
}
/// <summary>
/// Returns the value of an extension.
/// </summary>
- public TExtension GetExtension<TExtension>(GeneratedExtension<TMessage, TExtension> extension) {
+ public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
object value = extensions[extension.Descriptor];
if (value == null) {
return (TExtension) extension.MessageDefaultInstance;
@@ -41,7 +41,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Returns one element of a repeated extension.
/// </summary>
- public TExtension GetExtension<TExtension>(GeneratedExtension<TMessage, IList<TExtension>> extension, int index) {
+ public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension, int index) {
return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]);
}
diff --git a/csharp/ProtocolBuffers/ExtensionRegistry.cs b/csharp/ProtocolBuffers/ExtensionRegistry.cs
index 9cda6a84..c8f31d37 100644
--- a/csharp/ProtocolBuffers/ExtensionRegistry.cs
+++ b/csharp/ProtocolBuffers/ExtensionRegistry.cs
@@ -88,7 +88,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Add an extension from a generated file to the registry.
/// </summary>
- public void Add<TContainer, TExtension> (GeneratedExtension<TContainer, TExtension> extension)
+ public void Add<TContainer, TExtension> (GeneratedExtensionBase<TContainer, TExtension> extension)
where TContainer : IMessage<TContainer> {
if (extension.Descriptor.MappedType == MappedType.Message) {
Add(new ExtensionInfo(extension.Descriptor, extension.MessageDefaultInstance));
diff --git a/csharp/ProtocolBuffers/GeneratedExtension.cs b/csharp/ProtocolBuffers/GeneratedExtension.cs
deleted file mode 100644
index 667b4531..00000000
--- a/csharp/ProtocolBuffers/GeneratedExtension.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-using Google.ProtocolBuffers.Descriptors;
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-
-namespace Google.ProtocolBuffers {
-
- public static class GeneratedExtension {
-
- public static GeneratedExtension<TContainer, TExtension> CreateExtension<TContainer, TExtension>(FieldDescriptor descriptor)
- where TContainer : IMessage<TContainer> {
- if (descriptor.IsRepeated) {
- throw new ArgumentException("Must call CreateRepeatedGeneratedExtension() for repeated types.");
- }
- return new GeneratedExtension<TContainer, TExtension>(descriptor);
- }
-
- public static GeneratedExtension<TContainer, IList<TExtension>> CreateRepeatedExtension<TContainer, TExtension>(FieldDescriptor descriptor)
- where TContainer : IMessage<TContainer> {
- if (descriptor.IsRepeated) {
- throw new ArgumentException("Must call CreateRepeatedGeneratedExtension() for repeated types.");
- }
- return new GeneratedExtension<TContainer, IList<TExtension>>(descriptor);
- }
- }
-
- /// <summary>
- /// Base class for all generated extensions.
- /// </summary>
- /// <remarks>
- /// The protocol compiler generates a static singleton instance of this
- /// class for each extension. For exmaple, imagine a .proto file with:
- /// <code>
- /// message Foo {
- /// extensions 1000 to max
- /// }
- ///
- /// extend Foo {
- /// optional int32 bar;
- /// }
- /// </code>
- /// Then MyProto.Foo.Bar has type GeneratedExtension&lt;MyProto.Foo,int&gt;.
- /// <para />
- /// In general, users should ignore the details of this type, and
- /// simply use the static singletons as parmaeters to the extension accessors
- /// in ExtendableMessage and ExtendableBuilder.
- /// </remarks>
- public class GeneratedExtension<TContainer, TExtension> where TContainer : IMessage<TContainer> {
- private readonly IMessage messageDefaultInstance;
- private readonly FieldDescriptor descriptor;
-
- internal GeneratedExtension(FieldDescriptor descriptor) {
- if (!descriptor.IsExtension) {
- throw new ArgumentException("GeneratedExtension given a regular (non-extension) field.");
- }
-
- this.descriptor = descriptor;
-
- switch (descriptor.MappedType) {
- case MappedType.Message:
- PropertyInfo defaultInstanceProperty = typeof(TExtension)
- .GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public);
- if (defaultInstanceProperty == null) {
- throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name);
- }
- messageDefaultInstance = (IMessage) defaultInstanceProperty.GetValue(null, null);
- break;
- case MappedType.Enum:
- // FIXME(jonskeet): May not need this
- //enumValueOf = getMethodOrDie(type, "valueOf",
- // EnumValueDescriptor.class);
- //enumGetValueDescriptor = getMethodOrDie(type, "getValueDescriptor");
- messageDefaultInstance = null;
- break;
- default:
- messageDefaultInstance = null;
- break;
- }
- }
-
- public FieldDescriptor Descriptor {
- get { return descriptor; }
- }
-
- public IMessage MessageDefaultInstance {
- get { return messageDefaultInstance; }
- }
-
- internal object SingularFromReflectionType(object p) {
- throw new System.NotImplementedException();
- }
-
- internal object FromReflectionType(object value) {
- throw new System.NotImplementedException();
- }
- }
-}
diff --git a/csharp/ProtocolBuffers/GeneratedExtensionBase.cs b/csharp/ProtocolBuffers/GeneratedExtensionBase.cs
new file mode 100644
index 00000000..40118388
--- /dev/null
+++ b/csharp/ProtocolBuffers/GeneratedExtensionBase.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers {
+ /// <summary>
+ /// Base type for all generated extensions.
+ /// </summary>
+ /// <remarks>
+ /// The protocol compiler generates a static singleton instance of this
+ /// class for each extension. For exmaple, imagine a .proto file with:
+ /// <code>
+ /// message Foo {
+ /// extensions 1000 to max
+ /// }
+ ///
+ /// extend Foo {
+ /// optional int32 bar;
+ /// }
+ /// </code>
+ /// Then MyProto.Foo.Bar has type GeneratedExtensionBase&lt;MyProto.Foo,int&gt;.
+ /// <para />
+ /// In general, users should ignore the details of this type, and
+ /// simply use the static singletons as parameters to the extension accessors
+ /// in ExtendableMessage and ExtendableBuilder.
+ /// The interface implemented by both GeneratedException and GeneratedRepeatException,
+ /// to make it easier to cope with repeats separately.
+ /// </remarks>
+ public abstract class GeneratedExtensionBase<TContainer, TExtension> {
+
+ private readonly FieldDescriptor descriptor;
+ private readonly IMessage messageDefaultInstance;
+
+ protected GeneratedExtensionBase(FieldDescriptor descriptor) {
+ if (!descriptor.IsExtension) {
+ throw new ArgumentException("GeneratedExtension given a regular (non-extension) field.");
+ }
+
+ this.descriptor = descriptor;
+ if (descriptor.MappedType == MappedType.Message) {
+ PropertyInfo defaultInstanceProperty = typeof(TExtension)
+ .GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public);
+ if (defaultInstanceProperty == null) {
+ throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name);
+ }
+ messageDefaultInstance = (IMessage)defaultInstanceProperty.GetValue(null, null);
+ }
+ }
+
+ public FieldDescriptor Descriptor {
+ get { return descriptor; }
+ }
+
+ /// <summary>
+ /// Returns the default message instance for extensions which are message types.
+ /// </summary>
+ public IMessage MessageDefaultInstance {
+ get { return messageDefaultInstance; }
+ }
+
+ public object SingularFromReflectionType(object value) {
+ switch (Descriptor.MappedType) {
+ case MappedType.Message:
+ if (value is TExtension) {
+ return value;
+ } else {
+ // It seems the copy of the embedded message stored inside the
+ // extended message is not of the exact type the user was
+ // expecting. This can happen if a user defines a
+ // GeneratedExtension manually and gives it a different type.
+ // This should not happen in normal use. But, to be nice, we'll
+ // copy the message to whatever type the caller was expecting.
+ return MessageDefaultInstance.CreateBuilderForType()
+ .MergeFrom((IMessage)value).Build();
+ }
+ case MappedType.Enum:
+ // Just return a boxed int - that can be unboxed to the enum
+ return ((EnumValueDescriptor) value).Number;
+ default:
+ return value;
+ }
+ }
+
+ public abstract object FromReflectionType(object value);
+ }
+} \ No newline at end of file
diff --git a/csharp/ProtocolBuffers/GeneratedRepeatException.cs b/csharp/ProtocolBuffers/GeneratedRepeatException.cs
new file mode 100644
index 00000000..d766d7f6
--- /dev/null
+++ b/csharp/ProtocolBuffers/GeneratedRepeatException.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Descriptors;
+using System.Collections;
+
+namespace Google.ProtocolBuffers {
+ /// <summary>
+ /// Class used to represent repeat extensions in generated classes.
+ /// </summary>
+ public class GeneratedRepeatExtension<TContainer, TExtensionElement> : GeneratedExtensionBase<TContainer, IList<TExtensionElement>> {
+ private GeneratedRepeatExtension(FieldDescriptor field) : base(field) {
+ }
+
+ public static GeneratedExtensionBase<TContainer, IList<TExtensionElement>> CreateInstance(FieldDescriptor descriptor) {
+ if (descriptor.IsRepeated) {
+ throw new ArgumentException("Must call GeneratedRepeatExtension.CreateInstance() for repeated types.");
+ }
+ return new GeneratedRepeatExtension<TContainer, TExtensionElement>(descriptor);
+ }
+
+ /// <summary>
+ /// Converts the list to the right type.
+ /// TODO(jonskeet): Check where this is used, and whether we need to convert
+ /// for primitive types.
+ /// </summary>
+ /// <param name="value"></param>
+ /// <returns></returns>
+ public override object FromReflectionType(object value) {
+ if (Descriptor.MappedType == MappedType.Message ||
+ Descriptor.MappedType == MappedType.Enum) {
+ // Must convert the whole list.
+ List<TExtensionElement> result = new List<TExtensionElement>();
+ foreach (object element in (IEnumerable) value) {
+ ((IList) result).Add(SingularFromReflectionType(element));
+ }
+ return result;
+ } else {
+ return value;
+ }
+ }
+ }
+}
diff --git a/csharp/ProtocolBuffers/GeneratedSingleExtension.cs b/csharp/ProtocolBuffers/GeneratedSingleExtension.cs
new file mode 100644
index 00000000..11805293
--- /dev/null
+++ b/csharp/ProtocolBuffers/GeneratedSingleExtension.cs
@@ -0,0 +1,26 @@
+using System;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// Generated extension for a singular field.
+ /// </remarks>
+ public class GeneratedSingleExtension<TContainer, TExtension> : GeneratedExtensionBase<TContainer, TExtension>
+ where TContainer : IMessage<TContainer> {
+
+ internal GeneratedSingleExtension(FieldDescriptor descriptor) : base(descriptor) {
+ }
+
+ public static GeneratedSingleExtension<TContainer, TExtension> CreateInstance(FieldDescriptor descriptor) {
+ if (descriptor.IsRepeated) {
+ throw new ArgumentException("Must call GeneratedRepeateExtension.CreateInstance() for repeated types.");
+ }
+ return new GeneratedSingleExtension<TContainer, TExtension>(descriptor);
+ }
+
+ public override object FromReflectionType(object value) {
+ return base.SingularFromReflectionType(value);
+ }
+ }
+}
diff --git a/csharp/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/ProtocolBuffers/ProtocolBuffers.csproj
index 0cd9e88e..3735adb7 100644
--- a/csharp/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/csharp/ProtocolBuffers/ProtocolBuffers.csproj
@@ -82,9 +82,11 @@
<Compile Include="FieldAccess\RepeatedMessageAccessor.cs" />
<Compile Include="FieldSet.cs" />
<Compile Include="GeneratedBuilder.cs" />
- <Compile Include="GeneratedExtension.cs" />
+ <Compile Include="GeneratedSingleExtension.cs" />
<Compile Include="GeneratedMessage.cs" />
+ <Compile Include="GeneratedRepeatException.cs" />
<Compile Include="IBuilder.cs" />
+ <Compile Include="GeneratedExtensionBase.cs" />
<Compile Include="IMessage.cs" />
<Compile Include="InvalidProtocolBufferException.cs" />
<Compile Include="IRpcChannel.cs" />