aboutsummaryrefslogtreecommitdiff
path: root/csharp/src/ProtocolBuffers/FieldAccess
diff options
context:
space:
mode:
authorJon Skeet <skeet@pobox.com>2015-06-09 19:30:44 +0100
committerJon Skeet <skeet@pobox.com>2015-06-09 19:30:44 +0100
commite38294a62d7f37c0661273a9a26fda16d557423f (patch)
tree316989251907553408e7b32a12792f496333e075 /csharp/src/ProtocolBuffers/FieldAccess
parentf52426827e4d5e8da7d205af538799740b5199b9 (diff)
downloadprotobuf-e38294a62d7f37c0661273a9a26fda16d557423f.tar.gz
protobuf-e38294a62d7f37c0661273a9a26fda16d557423f.tar.bz2
protobuf-e38294a62d7f37c0661273a9a26fda16d557423f.zip
First pass at the mutable API. Quite a bit more to do - in particular, it's pretty slow right now.
Diffstat (limited to 'csharp/src/ProtocolBuffers/FieldAccess')
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs38
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs104
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs59
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs13
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs57
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs83
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs37
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs97
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs158
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs75
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs89
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs91
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs162
13 files changed, 215 insertions, 848 deletions
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs
new file mode 100644
index 00000000..51b94931
--- /dev/null
+++ b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using Google.Protobuf;
+using Google.Protobuf.FieldAccess;
+
+namespace Google.Protobuf.FieldAccess
+{
+ /// <summary>
+ /// Base class for field accessors.
+ /// </summary>
+ /// <typeparam name="T">Type of message containing the field</typeparam>
+ internal abstract class FieldAccessorBase<T> : IFieldAccessor<T> where T : IMessage<T>
+ {
+ private readonly Func<T, object> getValueDelegate;
+
+ internal FieldAccessorBase(string name)
+ {
+ PropertyInfo property = typeof(T).GetProperty(name);
+ if (property == null || !property.CanRead)
+ {
+ throw new ArgumentException("Not all required properties/methods available");
+ }
+ getValueDelegate = ReflectionUtil.CreateUpcastDelegate<T>(property.GetGetMethod());
+ }
+
+ public object GetValue(T message)
+ {
+ return getValueDelegate(message);
+ }
+
+ public abstract bool HasValue(T message);
+ public abstract void Clear(T message);
+ public abstract void SetValue(T message, object value);
+ }
+}
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
index ad1a4382..c3dbb75a 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
@@ -30,108 +30,51 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
-using Google.ProtocolBuffers.Descriptors;
+using Google.Protobuf.Descriptors;
-namespace Google.ProtocolBuffers.FieldAccess
+namespace Google.Protobuf.FieldAccess
{
/// <summary>
/// Provides access to fields in generated messages via reflection.
- /// This type is public to allow it to be used by generated messages, which
- /// create appropriate instances in the .proto file description class.
- /// TODO(jonskeet): See if we can hide it somewhere...
/// </summary>
- public sealed class FieldAccessorTable<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
+ public sealed class FieldAccessorTable<T> where T : IMessage<T>
{
- private readonly IFieldAccessor<TMessage, TBuilder>[] accessors;
- private readonly OneofAccessor<TMessage, TBuilder>[] oneofs;
-
+ private readonly IFieldAccessor<T>[] accessors;
private readonly MessageDescriptor descriptor;
- public MessageDescriptor Descriptor
- {
- get { return descriptor; }
- }
-
/// <summary>
/// Constructs a FieldAccessorTable for a particular message class.
/// Only one FieldAccessorTable should be constructed per class.
- /// The property names should all actually correspond with the field descriptor's
- /// CSharpOptions.PropertyName property, but bootstrapping issues currently
- /// prevent us from using that. This may be addressed at a future time, in which case
- /// we can keep this constructor for backwards compatibility, just ignoring the parameter.
- /// TODO(jonskeet): Make it so.
/// </summary>
/// <param name="descriptor">The type's descriptor</param>
/// <param name="propertyNames">The Pascal-case names of all the field-based properties in the message.</param>
- public FieldAccessorTable(MessageDescriptor descriptor, String[] propertyNames)
+ public FieldAccessorTable(MessageDescriptor descriptor, string[] propertyNames)
{
this.descriptor = descriptor;
- accessors = new IFieldAccessor<TMessage, TBuilder>[descriptor.Fields.Count];
- oneofs = new OneofAccessor<TMessage, TBuilder>[descriptor.Oneofs.Count];
+ accessors = new IFieldAccessor<T>[descriptor.Fields.Count];
bool supportFieldPresence = descriptor.File.Syntax == FileDescriptor.ProtoSyntax.Proto2;
- int fieldSize = accessors.Length;
- for (int i = 0; i < fieldSize; i++)
- {
- FieldDescriptor field = descriptor.Fields[i];
- string containingOneofName = (field.ContainingOneof != null) ?
- propertyNames[fieldSize +field.ContainingOneof.Index] : null;
- accessors[i] = CreateAccessor(
- field, propertyNames[i], containingOneofName, supportFieldPresence);
- }
- for (int i = 0; i < oneofs.Length; i++)
+ for (int i = 0; i < accessors.Length; i++)
{
- oneofs[i] = new OneofAccessor<TMessage, TBuilder>(descriptor, propertyNames[i + accessors.Length]);
+ var field = descriptor.Fields[i];
+ var name = propertyNames[i];
+ accessors[i] = field.IsRepeated
+ ? (IFieldAccessor<T>) new RepeatedFieldAccessor<T>(propertyNames[i])
+ : new SingleFieldAccessor<T>(field, name, supportFieldPresence);
}
+ // TODO(jonskeet): Oneof support
}
- /// <summary>
- /// Creates an accessor for a single field
- /// </summary>
- private static IFieldAccessor<TMessage, TBuilder> CreateAccessor(
- FieldDescriptor field, string name, string containingOneofName, bool supportFieldPresence)
+ internal IFieldAccessor<T> this[int fieldNumber]
{
- if (field.IsRepeated)
- {
- switch (field.MappedType)
- {
- case MappedType.Message:
- return new RepeatedMessageAccessor<TMessage, TBuilder>(name);
- case MappedType.Enum:
- return new RepeatedEnumAccessor<TMessage, TBuilder>(field, name);
- default:
- return new RepeatedPrimitiveAccessor<TMessage, TBuilder>(name);
- }
- }
- else
+ get
{
- switch (field.MappedType)
- {
- case MappedType.Message:
- {
- if (field.ContainingOneof != null)
- {
- return new SingleMessageAccessor<TMessage, TBuilder>(
- field, name, containingOneofName, supportFieldPresence);
- }
- else
- {
- return new SingleMessageAccessor<TMessage, TBuilder>(
- field, name, containingOneofName, true);
- }
- }
- case MappedType.Enum:
- return new SingleEnumAccessor<TMessage, TBuilder>(
- field, name, containingOneofName, supportFieldPresence);
- default:
- return new SinglePrimitiveAccessor<TMessage, TBuilder>(
- field, name, containingOneofName, supportFieldPresence);
- }
+ FieldDescriptor field = descriptor.FindFieldByNumber(fieldNumber);
+ // TODO: Handle extensions.
+ return accessors[field.Index];
}
}
- internal IFieldAccessor<TMessage, TBuilder> this[FieldDescriptor field]
+ internal IFieldAccessor<T> this[FieldDescriptor field]
{
get
{
@@ -148,14 +91,5 @@ namespace Google.ProtocolBuffers.FieldAccess
return accessors[field.Index];
}
}
-
- internal OneofAccessor<TMessage, TBuilder> Oneof(OneofDescriptor oneof)
- {
- if (oneof.ContainingType != descriptor)
- {
- throw new ArgumentException("OneofDescriptor does not match message type");
- }
- return oneofs[oneof.Index];
- }
}
} \ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
index 39d3b85b..7767fb02 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
@@ -30,66 +30,39 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-namespace Google.ProtocolBuffers.FieldAccess
+namespace Google.Protobuf.FieldAccess
{
/// <summary>
/// Allows fields to be reflectively accessed in a smart manner.
/// The property descriptors for each field are created once and then cached.
/// In addition, this interface holds knowledge of repeated fields, builders etc.
/// </summary>
- internal interface IFieldAccessor<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
+ internal interface IFieldAccessor<T> where T : IMessage<T>
{
/// <summary>
- /// Indicates whether the specified message contains the field.
+ /// Indicates whether the specified message contains the field. For primitive fields
+ /// declared in proto3-syntax messages, this simply checks whether the value is the default one.
/// </summary>
- bool Has(TMessage message);
+ /// <exception cref="InvalidOperationException">The field is a repeated field, or a single primitive field.</exception>
+ bool HasValue(T message);
/// <summary>
- /// Gets the count of the repeated field in the specified message.
+ /// Clears the field in the specified message. (For repeated fields,
+ /// this clears the list.)
/// </summary>
- int GetRepeatedCount(TMessage message);
+ void Clear(T message);
/// <summary>
- /// Clears the field in the specified builder.
+ /// Fetches the field value. For repeated values, this will be an
+ /// <see cref="IList"/> implementation.
/// </summary>
- /// <param name="builder"></param>
- void Clear(TBuilder builder);
+ object GetValue(T message);
/// <summary>
- /// Creates a builder for the type of this field (which must be a message field).
+ /// Mutator for single fields only. (Repeated fields must be mutated
+ /// by fetching the list, then mutating that.)
/// </summary>
- IBuilder CreateBuilder();
-
- /// <summary>
- /// Accessor for single fields
- /// </summary>
- object GetValue(TMessage message);
-
- /// <summary>
- /// Mutator for single fields
- /// </summary>
- void SetValue(TBuilder builder, object value);
-
- /// <summary>
- /// Accessor for repeated fields
- /// </summary>
- object GetRepeatedValue(TMessage message, int index);
-
- /// <summary>
- /// Mutator for repeated fields
- /// </summary>
- void SetRepeated(TBuilder builder, int index, object value);
-
- /// <summary>
- /// Adds the specified value to the field in the given builder.
- /// </summary>
- void AddRepeated(TBuilder builder, object value);
-
- /// <summary>
- /// Returns a read-only wrapper around the value of a repeated field.
- /// </summary>
- object GetRepeatedWrapper(TBuilder builder);
+ /// <exception cref="InvalidOperationException">The field is a repeated field.</exception>
+ void SetValue(T message, object value);
}
} \ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs
index 1a4bda76..85a929b7 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs
@@ -29,17 +29,18 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Reflection;
-using Google.ProtocolBuffers.Descriptors;
+using Google.Protobuf.Descriptors;
-namespace Google.ProtocolBuffers.FieldAccess
+namespace Google.Protobuf.FieldAccess
{
+ // TODO(jonskeet): Add "new" oneof API support
+
/// <summary>
/// Access for an oneof
/// </summary>
- internal class OneofAccessor<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
+ internal class OneofAccessor<TMessage> where TMessage : IMessage<TMessage>
{
+ /*
private readonly Func<TMessage, object> caseDelegate;
private readonly Func<TBuilder, IBuilder> clearDelegate;
private MessageDescriptor descriptor;
@@ -86,6 +87,6 @@ namespace Google.ProtocolBuffers.FieldAccess
return descriptor.FindFieldByNumber(fieldNumber);
}
return null;
- }
+ }*/
}
}
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs b/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
index 798f0dd7..b3d1c90d 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
@@ -32,7 +32,7 @@
using System;
using System.Reflection;
-namespace Google.ProtocolBuffers.FieldAccess
+namespace Google.Protobuf.FieldAccess
{
/// <summary>
/// The methods in this class are somewhat evil, and should not be tampered with lightly.
@@ -72,7 +72,7 @@ namespace Google.ProtocolBuffers.FieldAccess
Func<TSource, TResult> getter = ReflectionUtil.CreateDelegateFunc<TSource, TResult>(method);
// Implicit upcast to object (within the delegate)
- return delegate(TSource source) { return getter(source); };
+ return source => getter(source);
}
/// <summary>
@@ -92,7 +92,7 @@ namespace Google.ProtocolBuffers.FieldAccess
// call Method(x, y)
Action<TSource, TParam> call = ReflectionUtil.CreateDelegateAction<TSource, TParam>(method);
- return delegate(TSource source, object parameter) { call(source, (TParam) parameter); };
+ return (source, parameter) => call(source, (TParam) parameter);
}
/// <summary>
@@ -117,73 +117,34 @@ namespace Google.ProtocolBuffers.FieldAccess
return delegate(TSource source, object parameter) { call(source, (TParam) parameter); };
}
- /// <summary>
- /// Creates a delegate which will execute the given static method and cast the result up to IBuilder.
- /// </summary>
- public static Func<IBuilder> CreateStaticUpcastDelegate(MethodInfo method)
- {
- MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateStaticUpcastDelegateImpl");
- MethodInfo closedImpl = openImpl.MakeGenericMethod(method.ReturnType);
- return (Func<IBuilder>) closedImpl.Invoke(null, new object[] {method});
- }
-
- public static Func<IBuilder> CreateStaticUpcastDelegateImpl<T>(MethodInfo method)
- {
- Func<T> call = ReflectionUtil.CreateDelegateFunc<T>(method);
- return delegate { return (IBuilder) call(); };
- }
-
-
internal static Func<TResult> CreateDelegateFunc<TResult>(MethodInfo method)
{
-#if !CF20
object tdelegate = Delegate.CreateDelegate(typeof(Func<TResult>), null, method);
return (Func<TResult>)tdelegate;
-#else
- return delegate() { return (TResult)method.Invoke(null, null); };
-#endif
}
internal static Func<T, TResult> CreateDelegateFunc<T, TResult>(MethodInfo method)
{
-#if !CF20
object tdelegate = Delegate.CreateDelegate(typeof(Func<T, TResult>), null, method);
return (Func<T, TResult>)tdelegate;
-#else
- if (method.IsStatic)
- {
- return delegate(T arg1) { return (TResult) method.Invoke(null, new object[] {arg1}); };
- }
- return delegate(T arg1) { return (TResult)method.Invoke(arg1, null); };
-#endif
}
internal static Func<T1, T2, TResult> CreateDelegateFunc<T1, T2, TResult>(MethodInfo method)
{
-#if !CF20
object tdelegate = Delegate.CreateDelegate(typeof(Func<T1, T2, TResult>), null, method);
return (Func<T1, T2, TResult>)tdelegate;
-#else
- if (method.IsStatic)
- {
- return delegate(T1 arg1, T2 arg2) { return (TResult) method.Invoke(null, new object[] {arg1, arg2}); };
- }
- return delegate(T1 arg1, T2 arg2) { return (TResult)method.Invoke(arg1, new object[] { arg2 }); };
-#endif
+ }
+
+ internal static Action<T> CreateDelegateAction<T>(MethodInfo method)
+ {
+ object tdelegate = Delegate.CreateDelegate(typeof(Action<T>), null, method);
+ return (Action<T>)tdelegate;
}
internal static Action<T1, T2> CreateDelegateAction<T1, T2>(MethodInfo method)
{
-#if !CF20
object tdelegate = Delegate.CreateDelegate(typeof(Action<T1, T2>), null, method);
return (Action<T1, T2>)tdelegate;
-#else
- if (method.IsStatic)
- {
- return delegate(T1 arg1, T2 arg2) { method.Invoke(null, new object[] {arg1, arg2}); };
- }
- return delegate(T1 arg1, T2 arg2) { method.Invoke(arg1, new object[] { arg2 }); };
-#endif
}
}
} \ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs
deleted file mode 100644
index 152c2e0a..00000000
--- a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-using System.Collections;
-using System.Collections.Generic;
-using Google.ProtocolBuffers.Collections;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.FieldAccess
-{
- /// <summary>
- /// Accessor for a repeated enum field.
- /// </summary>
- internal sealed class RepeatedEnumAccessor<TMessage, TBuilder> : RepeatedPrimitiveAccessor<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
- {
- private readonly EnumDescriptor enumDescriptor;
-
- internal RepeatedEnumAccessor(FieldDescriptor field, string name) : base(name)
- {
- enumDescriptor = field.EnumType;
- }
-
- public override object GetValue(TMessage message)
- {
- List<EnumValueDescriptor> ret = new List<EnumValueDescriptor>();
- foreach (int rawValue in (IEnumerable) base.GetValue(message))
- {
- ret.Add(enumDescriptor.FindValueByNumber(rawValue));
- }
- return Lists.AsReadOnly(ret);
- }
-
- public override object GetRepeatedValue(TMessage message, int index)
- {
- // Note: This relies on the fact that the CLR allows unboxing from an enum to
- // its underlying value
- int rawValue = (int) base.GetRepeatedValue(message, index);
- return enumDescriptor.FindValueByNumber(rawValue);
- }
-
- public override void AddRepeated(TBuilder builder, object value)
- {
- ThrowHelper.ThrowIfNull(value, "value");
- base.AddRepeated(builder, ((EnumValueDescriptor) value).Number);
- }
-
- public override void SetRepeated(TBuilder builder, int index, object value)
- {
- ThrowHelper.ThrowIfNull(value, "value");
- base.SetRepeated(builder, index, ((EnumValueDescriptor) value).Number);
- }
- }
-} \ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs
new file mode 100644
index 00000000..aea721de
--- /dev/null
+++ b/csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Google.Protobuf;
+
+namespace Google.Protobuf.FieldAccess
+{
+ /// <summary>
+ /// Accessor for repeated fields.
+ /// </summary>
+ /// <typeparam name="T">The type of message containing the field.</typeparam>
+ internal sealed class RepeatedFieldAccessor<T> : FieldAccessorBase<T> where T : IMessage<T>
+ {
+ internal RepeatedFieldAccessor(string name) : base(name)
+ {
+ }
+
+ public override void Clear(T message)
+ {
+ IList list = (IList) GetValue(message);
+ list.Clear();
+ }
+
+ public override bool HasValue(T message)
+ {
+ throw new NotImplementedException("HasValue is not implemented for repeated fields");
+ }
+
+ public override void SetValue(T message, object value)
+ {
+ throw new NotImplementedException("SetValue is not implemented for repeated fields");
+ }
+
+ }
+}
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
deleted file mode 100644
index fd18b904..00000000
--- a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-using System;
-using System.Reflection;
-
-namespace Google.ProtocolBuffers.FieldAccess
-{
- /// <summary>
- /// Accessor for a repeated message field.
- ///
- /// TODO(jonskeet): Try to extract the commonality between this and SingleMessageAccessor.
- /// We almost want multiple inheritance...
- /// </summary>
- internal sealed class RepeatedMessageAccessor<TMessage, TBuilder> : RepeatedPrimitiveAccessor<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
- {
- /// <summary>
- /// The static method to create a builder for the property type. For example,
- /// in a message type "Foo", a field called "bar" might be of type "Baz". This
- /// method is Baz.CreateBuilder.
- /// </summary>
- private readonly Func<IBuilder> createBuilderDelegate;
-
- internal RepeatedMessageAccessor(string name) : base(name)
- {
- MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", EmptyTypes);
- if (createBuilderMethod == null)
- {
- throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);
- }
- createBuilderDelegate = ReflectionUtil.CreateStaticUpcastDelegate(createBuilderMethod);
- }
-
- /// <summary>
- /// Creates a message of the appropriate CLR type from the given value,
- /// which may already be of the right type or may be a dynamic message.
- /// </summary>
- private object CoerceType(object value)
- {
- ThrowHelper.ThrowIfNull(value, "value");
- // If it's already of the right type, we're done
- if (ClrType.IsInstanceOfType(value))
- {
- return value;
- }
-
- // No... so let's create a builder of the right type, and merge the value in.
- IMessageLite message = (IMessageLite) value;
- return CreateBuilder().WeakMergeFrom(message).WeakBuild();
- }
-
- public override void SetRepeated(TBuilder builder, int index, object value)
- {
- base.SetRepeated(builder, index, CoerceType(value));
- }
-
- public override IBuilder CreateBuilder()
- {
- return createBuilderDelegate();
- }
-
- public override void AddRepeated(TBuilder builder, object value)
- {
- base.AddRepeated(builder, CoerceType(value));
- }
- }
-} \ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs
deleted file mode 100644
index d3b926bc..00000000
--- a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs
+++ /dev/null
@@ -1,158 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-using System;
-using System.Collections;
-using System.Reflection;
-
-namespace Google.ProtocolBuffers.FieldAccess
-{
- /// <summary>
- /// Accessor for a repeated field of type int, ByteString etc.
- /// </summary>
- internal class RepeatedPrimitiveAccessor<TMessage, TBuilder> : IFieldAccessor<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
- {
- private readonly Type clrType;
- private readonly Func<TMessage, object> getValueDelegate;
- private readonly Func<TBuilder, IBuilder> clearDelegate;
- private readonly Action<TBuilder, object> addValueDelegate;
- private readonly Func<TBuilder, object> getRepeatedWrapperDelegate;
- private readonly Func<TMessage, int> countDelegate;
- private readonly MethodInfo getElementMethod;
- private readonly MethodInfo setElementMethod;
-
- // Replacement for Type.EmptyTypes which apparently isn't available on the compact framework
- internal static readonly Type[] EmptyTypes = new Type[0];
-
- /// <summary>
- /// The CLR type of the field (int, the enum type, ByteString, the message etc).
- /// This is taken from the return type of the method used to retrieve a single
- /// value.
- /// </summary>
- protected Type ClrType
- {
- get { return clrType; }
- }
-
- internal RepeatedPrimitiveAccessor(string name)
- {
- PropertyInfo messageProperty = typeof(TMessage).GetProperty(name + "List");
- PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name + "List");
- PropertyInfo countProperty = typeof(TMessage).GetProperty(name + "Count");
- MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, EmptyTypes);
- getElementMethod = typeof(TMessage).GetMethod("Get" + name, new Type[] {typeof(int)});
- clrType = getElementMethod.ReturnType;
- MethodInfo addMethod = typeof(TBuilder).GetMethod("Add" + name, new Type[] {ClrType});
- setElementMethod = typeof(TBuilder).GetMethod("Set" + name, new Type[] {typeof(int), ClrType});
- if (messageProperty == null
- || builderProperty == null
- || countProperty == null
- || clearMethod == null
- || addMethod == null
- || getElementMethod == null
- || setElementMethod == null)
- {
- throw new ArgumentException("Not all required properties/methods available");
- }
- clearDelegate = ReflectionUtil.CreateDelegateFunc<TBuilder, IBuilder>(clearMethod);
- countDelegate = ReflectionUtil.CreateDelegateFunc<TMessage, int>(countProperty.GetGetMethod());
- getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod());
- addValueDelegate = ReflectionUtil.CreateDowncastDelegateIgnoringReturn<TBuilder>(addMethod);
- getRepeatedWrapperDelegate = ReflectionUtil.CreateUpcastDelegate<TBuilder>(builderProperty.GetGetMethod());
- }
-
- public bool Has(TMessage message)
- {
- throw new InvalidOperationException();
- }
-
- public virtual IBuilder CreateBuilder()
- {
- throw new InvalidOperationException();
- }
-
- public virtual object GetValue(TMessage message)
- {
- return getValueDelegate(message);
- }
-
- public void SetValue(TBuilder builder, object value)
- {
- // Add all the elements individually. This serves two purposes:
- // 1) Verifies that each element has the correct type.
- // 2) Insures that the caller cannot modify the list later on and
- // have the modifications be reflected in the message.
- Clear(builder);
- foreach (object element in (IEnumerable) value)
- {
- AddRepeated(builder, element);
- }
- }
-
- public void Clear(TBuilder builder)
- {
- clearDelegate(builder);
- }
-
- public int GetRepeatedCount(TMessage message)
- {
- return countDelegate(message);
- }
-
- public virtual object GetRepeatedValue(TMessage message, int index)
- {
- return getElementMethod.Invoke(message, new object[] {index});
- }
-
- public virtual void SetRepeated(TBuilder builder, int index, object value)
- {
- ThrowHelper.ThrowIfNull(value, "value");
- setElementMethod.Invoke(builder, new object[] {index, value});
- }
-
- public virtual void AddRepeated(TBuilder builder, object value)
- {
- ThrowHelper.ThrowIfNull(value, "value");
- addValueDelegate(builder, value);
- }
-
- /// <summary>
- /// The builder class's accessor already builds a read-only wrapper for
- /// us, which is exactly what we want.
- /// </summary>
- public object GetRepeatedWrapper(TBuilder builder)
- {
- return getRepeatedWrapperDelegate(builder);
- }
- }
-} \ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
deleted file mode 100644
index 89e10179..00000000
--- a/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.FieldAccess
-{
- /// <summary>
- /// Accessor for fields representing a non-repeated enum value.
- /// </summary>
- internal sealed class SingleEnumAccessor<TMessage, TBuilder> : SinglePrimitiveAccessor<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
- {
- private readonly EnumDescriptor enumDescriptor;
-
- internal SingleEnumAccessor(FieldDescriptor field, string name, string containingOneofName, bool supportFieldPresence)
- : base(field, name, containingOneofName, supportFieldPresence)
- {
- enumDescriptor = field.EnumType;
- }
-
- /// <summary>
- /// Returns an EnumValueDescriptor representing the value in the builder.
- /// Note that if an enum has multiple values for the same number, the descriptor
- /// for the first value with that number will be returned.
- /// </summary>
- public override object GetValue(TMessage message)
- {
- // Note: This relies on the fact that the CLR allows unboxing from an enum to
- // its underlying value
- int rawValue = (int) base.GetValue(message);
- return enumDescriptor.FindValueByNumber(rawValue);
- }
-
- /// <summary>
- /// Sets the value as an enum (via an int) in the builder,
- /// from an EnumValueDescriptor parameter.
- /// </summary>
- public override void SetValue(TBuilder builder, object value)
- {
- ThrowHelper.ThrowIfNull(value, "value");
- EnumValueDescriptor valueDescriptor = (EnumValueDescriptor) value;
- base.SetValue(builder, valueDescriptor.Number);
- }
- }
-} \ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs
new file mode 100644
index 00000000..a352d3a2
--- /dev/null
+++ b/csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using Google.Protobuf;
+using Google.Protobuf.Descriptors;
+using Google.Protobuf.FieldAccess;
+
+namespace Google.Protobuf.FieldAccess
+{
+ /// <summary>
+ /// Accessor for single fields.
+ /// </summary>
+ /// <typeparam name="T">The type of message containing the field.</typeparam>
+ internal sealed class SingleFieldAccessor<T> : FieldAccessorBase<T> where T : IMessage<T>
+ {
+ // All the work here is actually done in the constructor - it creates the appropriate delegates.
+ // There are various cases to consider, based on the property type (message, string/bytes, or "genuine" primitive)
+ // and proto2 vs proto3 for non-message types, as proto3 doesn't support "full" presence detection or default
+ // values.
+
+ private readonly Action<T, object> setValueDelegate;
+ private readonly Action<T> clearDelegate;
+ private readonly Func<T, bool> hasValueDelegate;
+
+ internal SingleFieldAccessor(FieldDescriptor descriptor, string name, bool supportsFieldPresence) : base(name)
+ {
+ PropertyInfo property = typeof(T).GetProperty(name);
+ // We know there *is* such a property, or the base class constructor would have thrown. We should be able to write
+ // to it though.
+ if (!property.CanWrite)
+ {
+ throw new ArgumentException("Not all required properties/methods available");
+ }
+ setValueDelegate = ReflectionUtil.CreateDowncastDelegate<T>(property.GetSetMethod());
+
+ var clrType = property.PropertyType;
+
+ if (typeof(IMessage).IsAssignableFrom(clrType))
+ {
+ // Message types are simple - we only need to detect nullity.
+ clearDelegate = message => SetValue(message, null);
+ hasValueDelegate = message => GetValue(message) == null;
+ }
+
+ if (supportsFieldPresence)
+ {
+ // Proto2: we expect a HasFoo property and a ClearFoo method.
+ // For strings and byte arrays, setting the property to null would have the equivalent effect,
+ // but we generate the method for consistency, which makes this simpler.
+ PropertyInfo hasProperty = typeof(T).GetProperty("Has" + name);
+ MethodInfo clearMethod = typeof(T).GetMethod("Clear" + name);
+ if (hasProperty == null || clearMethod == null || !hasProperty.CanRead)
+ {
+ throw new ArgumentException("Not all required properties/methods available");
+ }
+ hasValueDelegate = ReflectionUtil.CreateDelegateFunc<T, bool>(hasProperty.GetGetMethod());
+ clearDelegate = ReflectionUtil.CreateDelegateAction<T>(clearMethod);
+ }
+ else
+ {
+ /*
+ // TODO(jonskeet): Reimplement. We need a better way of working out default values.
+ // Proto3: for field detection, we just need the default value of the field (0, "", byte[0] etc)
+ // To clear a field, we set the value to that default.
+ object defaultValue = descriptor.DefaultValue;
+ hasValueDelegate = message => GetValue(message).Equals(defaultValue);
+ clearDelegate = message => SetValue(message, defaultValue);
+ */
+ }
+ }
+
+ public override bool HasValue(T message)
+ {
+ return hasValueDelegate(message);
+ }
+
+ public override void Clear(T message)
+ {
+ clearDelegate(message);
+ }
+
+ public override void SetValue(T message, object value)
+ {
+ setValueDelegate(message, value);
+ }
+ }
+}
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
deleted file mode 100644
index 9068d40a..00000000
--- a/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-using System;
-using System.Reflection;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.FieldAccess
-{
- /// <summary>
- /// Accessor for fields representing a non-repeated message value.
- /// </summary>
- internal sealed class SingleMessageAccessor<TMessage, TBuilder> : SinglePrimitiveAccessor<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
- {
- /// <summary>
- /// The static method to create a builder for the property type. For example,
- /// in a message type "Foo", a field called "bar" might be of type "Baz". This
- /// method is Baz.CreateBuilder.
- /// </summary>
- private readonly Func<IBuilder> createBuilderDelegate;
-
- internal SingleMessageAccessor(FieldDescriptor field, string name, string containingOneofName, bool supportFieldPresence)
- : base(field, name, containingOneofName, supportFieldPresence)
- {
- MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", ReflectionUtil.EmptyTypes);
- if (createBuilderMethod == null)
- {
- throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);
- }
- createBuilderDelegate = ReflectionUtil.CreateStaticUpcastDelegate(createBuilderMethod);
- }
-
- /// <summary>
- /// Creates a message of the appropriate CLR type from the given value,
- /// which may already be of the right type or may be a dynamic message.
- /// </summary>
- private object CoerceType(object value)
- {
- ThrowHelper.ThrowIfNull(value, "value");
- // If it's already of the right type, we're done
- if (ClrType.IsInstanceOfType(value))
- {
- return value;
- }
-
- // No... so let's create a builder of the right type, and merge the value in.
- IMessageLite message = (IMessageLite) value;
- return CreateBuilder().WeakMergeFrom(message).WeakBuild();
- }
-
- public override void SetValue(TBuilder builder, object value)
- {
- base.SetValue(builder, CoerceType(value));
- }
-
- public override IBuilder CreateBuilder()
- {
- return createBuilderDelegate();
- }
- }
-} \ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
deleted file mode 100644
index 035fcf3c..00000000
--- a/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-using System;
-using System.Reflection;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.FieldAccess
-{
- /// <summary>
- /// Access for a non-repeated field of a "primitive" type (i.e. not another message or an enum).
- /// </summary>
- internal class SinglePrimitiveAccessor<TMessage, TBuilder> : IFieldAccessor<TMessage, TBuilder>
- where TMessage : IMessage<TMessage, TBuilder>
- where TBuilder : IBuilder<TMessage, TBuilder>
- {
- private readonly Type clrType;
- private readonly Func<TMessage, object> getValueDelegate;
- private readonly Action<TBuilder, object> setValueDelegate;
- private readonly Func<TMessage, bool> hasDelegate;
- private readonly Func<TBuilder, IBuilder> clearDelegate;
- private readonly Func<TMessage, object> caseDelegate;
-
- /// <summary>
- /// The CLR type of the field (int, the enum type, ByteString, the message etc).
- /// As declared by the property.
- /// </summary>
- protected Type ClrType
- {
- get { return clrType; }
- }
-
- internal SinglePrimitiveAccessor(
- FieldDescriptor fieldDescriptor, string name, string containingOneofName, bool supportFieldPresence)
- {
- PropertyInfo messageProperty = typeof(TMessage).GetProperty(name, null, ReflectionUtil.EmptyTypes);
- PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name, null, ReflectionUtil.EmptyTypes);
- MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name);
- if (messageProperty == null || builderProperty == null || clearMethod == null)
- {
- throw new ArgumentException("Not all required properties/methods available");
- }
-
- if (supportFieldPresence)
- {
- PropertyInfo hasProperty = typeof(TMessage).GetProperty("Has" + name);
- if (hasProperty == null)
- {
- throw new ArgumentException("Has properties not available");
- }
- hasDelegate = ReflectionUtil.CreateDelegateFunc<TMessage, bool>(hasProperty.GetGetMethod());
- } else
- {
- if (fieldDescriptor.ContainingOneof != null)
- {
- PropertyInfo caseProperty = typeof(TMessage).GetProperty(containingOneofName + "Case");
- caseDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(caseProperty.GetGetMethod());
- hasDelegate = message => OneofFieldNumber(message).Equals(fieldDescriptor.FieldNumber);
- }
- else
- {
- hasDelegate = message => !GetValue(message).Equals(fieldDescriptor.DefaultValue);
- }
- }
-
- clrType = messageProperty.PropertyType;
- clearDelegate = ReflectionUtil.CreateDelegateFunc<TBuilder, IBuilder>(clearMethod);
- getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod());
- setValueDelegate = ReflectionUtil.CreateDowncastDelegate<TBuilder>(builderProperty.GetSetMethod());
- }
-
- private int OneofFieldNumber(TMessage message)
- {
- return (int) caseDelegate(message);
- }
-
- public bool Has(TMessage message)
- {
- return hasDelegate(message);
- }
-
- public void Clear(TBuilder builder)
- {
- clearDelegate(builder);
- }
-
- /// <summary>
- /// Only valid for message types - this implementation throws InvalidOperationException.
- /// </summary>
- public virtual IBuilder CreateBuilder()
- {
- throw new InvalidOperationException();
- }
-
- public virtual object GetValue(TMessage message)
- {
- return getValueDelegate(message);
- }
-
- public virtual void SetValue(TBuilder builder, object value)
- {
- setValueDelegate(builder, value);
- }
-
- #region Methods only related to repeated values
-
- public int GetRepeatedCount(TMessage message)
- {
- throw new InvalidOperationException();
- }
-
- public object GetRepeatedValue(TMessage message, int index)
- {
- throw new InvalidOperationException();
- }
-
- public void SetRepeated(TBuilder builder, int index, object value)
- {
- throw new InvalidOperationException();
- }
-
- public void AddRepeated(TBuilder builder, object value)
- {
- throw new InvalidOperationException();
- }
-
- public object GetRepeatedWrapper(TBuilder builder)
- {
- throw new InvalidOperationException();
- }
-
- #endregion
- }
-}