Commit 3f9a6f21 authored by Jon Skeet's avatar Jon Skeet

Implemented GeneratedExtension, although list handling may be incorrect.

parent 575083ae
......@@ -522,8 +522,8 @@ namespace Google.ProtocolBuffers.TestProtos {
#region Nested types
public static class Types {
public static readonly pb::GeneratedExtension<self::TestMessageSet, self::TestMessageSetExtension1> MessageSetExtension =
pb::GeneratedExtension.CreateExtension<self::TestMessageSet, self::TestMessageSetExtension1>(Descriptor.Extensions[0]);
public static readonly pb::GeneratedExtensionBase<self::TestMessageSet, self::TestMessageSetExtension1> MessageSetExtension =
pb::GeneratedSingleExtension<self::TestMessageSet, self::TestMessageSetExtension1>.CreateInstance(Descriptor.Extensions[0]);
}
#endregion
......@@ -731,8 +731,8 @@ namespace Google.ProtocolBuffers.TestProtos {
#region Nested types
public static class Types {
public static readonly pb::GeneratedExtension<self::TestMessageSet, self::TestMessageSetExtension2> MessageSetExtension =
pb::GeneratedExtension.CreateExtension<self::TestMessageSet, self::TestMessageSetExtension2>(Descriptor.Extensions[0]);
public static readonly pb::GeneratedExtensionBase<self::TestMessageSet, self::TestMessageSetExtension2> MessageSetExtension =
pb::GeneratedSingleExtension<self::TestMessageSet, self::TestMessageSetExtension2>.CreateInstance(Descriptor.Extensions[0]);
}
#endregion
......
......@@ -81,8 +81,8 @@ namespace Google.ProtocolBuffers.TestProtos {
#region Nested types
public static class Types {
public static readonly pb::GeneratedExtension<self::TestOptimizedForSize, int> TestExtension =
pb::GeneratedExtension.CreateExtension<self::TestOptimizedForSize, int>(Descriptor.Extensions[0]);
public static readonly pb::GeneratedExtensionBase<self::TestOptimizedForSize, int> TestExtension =
pb::GeneratedSingleExtension<self::TestOptimizedForSize, int>.CreateInstance(Descriptor.Extensions[0]);
}
#endregion
......
......@@ -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]);
}
......
......@@ -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));
......
using Google.ProtocolBuffers.Descriptors;
using System;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
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.
/// Base type for all generated extensions.
/// </summary>
/// <remarks>
/// The protocol compiler generates a static singleton instance of this
......@@ -39,42 +20,32 @@ namespace Google.ProtocolBuffers {
/// optional int32 bar;
/// }
/// </code>
/// Then MyProto.Foo.Bar has type GeneratedExtension&lt;MyProto.Foo,int&gt;.
/// 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 parmaeters to the extension accessors
/// 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 class GeneratedExtension<TContainer, TExtension> where TContainer : IMessage<TContainer> {
private readonly IMessage messageDefaultInstance;
public abstract class GeneratedExtensionBase<TContainer, TExtension> {
private readonly FieldDescriptor descriptor;
private readonly IMessage messageDefaultInstance;
internal GeneratedExtension(FieldDescriptor descriptor) {
protected GeneratedExtensionBase(FieldDescriptor descriptor) {
if (!descriptor.IsExtension) {
throw new ArgumentException("GeneratedExtension given a regular (non-extension) field.");
}
this.descriptor = descriptor;
switch (descriptor.MappedType) {
case MappedType.Message:
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);
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;
messageDefaultInstance = (IMessage)defaultInstanceProperty.GetValue(null, null);
}
}
......@@ -82,16 +53,36 @@ namespace Google.ProtocolBuffers {
get { return descriptor; }
}
/// <summary>
/// Returns the default message instance for extensions which are message types.
/// </summary>
public IMessage MessageDefaultInstance {
get { return messageDefaultInstance; }
}
internal object SingularFromReflectionType(object p) {
throw new System.NotImplementedException();
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;
}
internal object FromReflectionType(object value) {
throw new System.NotImplementedException();
}
public abstract object FromReflectionType(object value);
}
}
\ No newline at end of file
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;
}
}
}
}
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);
}
}
}
......@@ -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" />
......
......@@ -57,12 +57,12 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
if (descriptor_->is_repeated()) {
printer->Print(vars,
"public static readonly\r\n"
" pb::GeneratedExtension<$containing_type$, scg::IList<$type$>> name =\r\n"
" pb::GeneratedExtension.CreateRepeatedExtension<$containing_type$, $type$>(Descriptor.Extensions[$index$]);\r\n");
" pb::GeneratedExtensionBase<$containing_type$, scg::IList<$type$>> name =\r\n"
" pb::GeneratedRepeatExtension<$containing_type$, $type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
} else {
printer->Print(vars,
"public static readonly pb::GeneratedExtension<$containing_type$, $type$> $name$ =\r\n"
" pb::GeneratedExtension.CreateExtension<$containing_type$, $type$>(Descriptor.Extensions[$index$]);\r\n");
"public static readonly pb::GeneratedExtensionBase<$containing_type$, $type$> $name$ =\r\n"
" pb::GeneratedSingleExtension<$containing_type$, $type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment