aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/csharp/csharp_message.cc
diff options
context:
space:
mode:
authorGravatar Jon Skeet <jonskeet@google.com>2015-07-01 14:47:03 +0100
committerGravatar Jon Skeet <jonskeet@google.com>2015-07-09 08:24:49 +0100
commit78ea98f56f7a0a028e378aee6394549707e199bc (patch)
treeb3275e8d8b01528dc58af6ec0877c4ee79cd1b54 /src/google/protobuf/compiler/csharp/csharp_message.cc
parent3805b43009d35422bed85c56aaf2d6ce4d007fe5 (diff)
Implement reflection properly for fields.
- FieldAccessorTable is now non-generic - We don't have a static field per message type in the umbrella class. (Message descriptors are accessed via the file descriptor.) - Removed the "descriptor assigner" complication from the descriptor fixup; without extensions, we don't need it - MapField implements IDictionary (more tests would be good...) - RepeatedField implements IList (more tests would be good) - Use expression trees to build accessors. (Will need to test this on various platforms... probably need a fallback strategy just using reflection directly.) - Added FieldDescriptor.IsMap - Added tests for reflection with generated messages Changes to generated code coming in next commit.
Diffstat (limited to 'src/google/protobuf/compiler/csharp/csharp_message.cc')
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.cc37
1 files changed, 22 insertions, 15 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index 9e2fe9b6..c7a1e290 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -116,8 +116,7 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
// The descriptor for this type.
printer->Print(
- "internal static pbd::MessageDescriptor internal__$identifier$__Descriptor;\n"
- "internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$> internal__$identifier$__FieldAccessorTable;\n",
+ "internal static pb::FieldAccess.FieldAccessorTable internal__$identifier$__FieldAccessorTable;\n",
"identifier", GetUniqueFileScopeIdentifier(descriptor_),
"full_class_name", full_class_name());
@@ -130,24 +129,23 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) {
map<string, string> vars;
vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_);
- vars["index"] = SimpleItoa(descriptor_->index());
vars["full_class_name"] = full_class_name();
- if (descriptor_->containing_type() != NULL) {
- vars["parent"] = GetUniqueFileScopeIdentifier(
- descriptor_->containing_type());
- }
- printer->Print(vars, "internal__$identifier$__Descriptor = ");
- if (!descriptor_->containing_type()) {
- printer->Print(vars, "Descriptor.MessageTypes[$index$];\n");
- } else {
- printer->Print(vars, "internal__$parent$__Descriptor.NestedTypes[$index$];\n");
+ // Work out how to get to the message descriptor (which may be multiply nested) from the file
+ // descriptor.
+ string descriptor_chain;
+ const Descriptor* current_descriptor = descriptor_;
+ while (current_descriptor->containing_type()) {
+ descriptor_chain = ".NestedTypes[" + SimpleItoa(current_descriptor->index()) + "]" + descriptor_chain;
+ current_descriptor = current_descriptor->containing_type();
}
+ descriptor_chain = "descriptor.MessageTypes[" + SimpleItoa(current_descriptor->index()) + "]" + descriptor_chain;
+ vars["descriptor_chain"] = descriptor_chain;
printer->Print(
vars,
"internal__$identifier$__FieldAccessorTable = \n"
- " new pb::FieldAccess.FieldAccessorTable<$full_class_name$>(internal__$identifier$__Descriptor,\n");
+ " new pb::FieldAccess.FieldAccessorTable(typeof($full_class_name$), $descriptor_chain$,\n");
printer->Print(" new string[] { ");
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("\"$property_name$\", ",
@@ -201,13 +199,22 @@ void MessageGenerator::Generate(io::Printer* printer) {
"private static readonly uint[] _fieldTags = new uint[] { $tags$ };\n",
"tags", JoinStrings(tags, ", "));
+ // Access the message descriptor via the relevant file descriptor or containing message descriptor.
+ if (!descriptor_->containing_type()) {
+ vars["descriptor_accessor"] = GetFullUmbrellaClassName(descriptor_->file())
+ + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
+ } else {
+ vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
+ + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
+ }
+
printer->Print(
vars,
"public static pbd::MessageDescriptor Descriptor {\n"
- " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n"
+ " get { return $descriptor_accessor$; }\n"
"}\n"
"\n"
- "public pb::FieldAccess.FieldAccessorTable<$class_name$> Fields {\n"
+ "public pb::FieldAccess.FieldAccessorTable Fields {\n"
" get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n"
"}\n"
"\n"