diff options
author | Jon Skeet <jonskeet@google.com> | 2015-07-20 19:24:31 +0100 |
---|---|---|
committer | Jon Skeet <jonskeet@google.com> | 2015-07-21 12:59:40 +0100 |
commit | 53c399a1d65df65e9f83a70b55041a01cf8d7489 (patch) | |
tree | bf3f738dd30295dc8ceb65478b9071d6d654e144 /src/google/protobuf/compiler/csharp/csharp_message.cc | |
parent | 2ee4b5665520fe3245eb5e15df8bd35e0c539a07 (diff) | |
download | protobuf-53c399a1d65df65e9f83a70b55041a01cf8d7489.tar.gz protobuf-53c399a1d65df65e9f83a70b55041a01cf8d7489.tar.bz2 protobuf-53c399a1d65df65e9f83a70b55041a01cf8d7489.zip |
Revamp to reflection.
Changes in brief:
1. Descriptor is now the entry point for all reflection.
2. IReflectedMessage has gone; there's now a Descriptor property in IMessage, which is explicitly implemented (due to the static property).
3. FieldAccessorTable has gone away
4. IFieldAccessor and OneofFieldAccessor still exist; we *could* put the functionality straight into FieldDescriptor and OneofDescriptor... I'm unsure about that.
5. There's a temporary property MessageDescriptor.FieldAccessorsByFieldNumber to make the test changes small - we probably want this to go away
6. Discovery for delegates is now via attributes applied to properties and the Clear method of a oneof
I'm happy with 1-3.
4 I'm unsure about - feedback welcome.
5 will go away
6 I'm unsure about, both in design and implementation. Should we have a ProtobufMessageAttribute too? Should we find all the relevant attributes in MessageDescriptor and pass them down, to avoid an O(N^2) scenario?
Generated code changes coming in the next commit.
Diffstat (limited to 'src/google/protobuf/compiler/csharp/csharp_message.cc')
-rw-r--r-- | src/google/protobuf/compiler/csharp/csharp_message.cc | 84 |
1 files changed, 5 insertions, 79 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 10cf3585..42fd5065 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -96,88 +96,11 @@ const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() return fields_by_number_; } -/// Get an identifier that uniquely identifies this type within the file. -/// This is used to declare static variables related to this type at the -/// outermost file scope. -std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) { - std::string result = descriptor->full_name(); - std::replace(result.begin(), result.end(), '.', '_'); - return "static_" + result; -} - -void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { - // Because descriptor.proto (Google.Protobuf.DescriptorProtos) is - // used in the construction of descriptors, we have a tricky bootstrapping - // problem. To help control static initialization order, we make sure all - // descriptors and other static data that depends on them are members of - // the proto-descriptor class. This way, they will be initialized in - // a deterministic order. - - std::string identifier = GetUniqueFileScopeIdentifier(descriptor_); - - // The descriptor for this type. - printer->Print( - "internal static pbr::FieldAccessorTable internal__$identifier$__FieldAccessorTable;\n", - "identifier", GetUniqueFileScopeIdentifier(descriptor_), - "full_class_name", full_class_name()); - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - // Don't generate accessor table fields for maps... - if (!IsMapEntryMessage(descriptor_->nested_type(i))) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariables(printer); - } - } -} - -void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { - map<string, string> vars; - vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); - vars["full_class_name"] = full_class_name(); - - // 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 pbr::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$\", ", - "property_name", GetPropertyName(descriptor_->field(i))); - } - printer->Print("}, new string[] { "); - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("\"$oneof_name$\", ", - "oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - printer->Print("});\n"); - - // Generate static member initializers for all non-map-entry nested types. - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - if (!IsMapEntryMessage(descriptor_->nested_type(i))) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariableInitializers(printer); - } - } -} - void MessageGenerator::Generate(io::Printer* printer) { map<string, string> vars; vars["class_name"] = class_name(); vars["access_level"] = class_access_level(); vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file()); - vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); printer->Print( "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); @@ -221,8 +144,8 @@ void MessageGenerator::Generate(io::Printer* printer) { " get { return $descriptor_accessor$; }\n" "}\n" "\n" - "pbr::FieldAccessorTable pb::IReflectedMessage.Fields {\n" - " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" + "pbr::MessageDescriptor pb::IMessage.Descriptor {\n" + " get { return Descriptor; }\n" "}\n" "\n" "private bool _frozen = false;\n" @@ -258,6 +181,7 @@ void MessageGenerator::Generate(io::Printer* printer) { for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + vars["original_name"] = descriptor_->oneof_decl(i)->name(); printer->Print( vars, "private object $name$_;\n" @@ -275,9 +199,11 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print( vars, "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n" + "[pbr::ProtobufOneof(\"$original_name$\")]\n" "public $property_name$OneofCase $property_name$Case {\n" " get { return $name$Case_; }\n" "}\n\n" + "[pbr::ProtobufOneof(\"$original_name$\")]\n" "public void Clear$property_name$() {\n" " pb::Freezable.CheckMutable(this);\n" " $name$Case_ = $property_name$OneofCase.None;\n" |