Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve C# reflection support #566

Merged
merged 10 commits into from Jul 10, 2015

Conversation

jskeet
Copy link
Contributor

@jskeet jskeet commented Jul 1, 2015

This is all relative to PR #561.

After this PR, reflection support is pretty reasonable. Outstanding changes I'd like to make (probably after the first merge)

  • Combine FieldAccess and Descriptors into a Reflection namespace
  • Add oneof reflection support
  • Rename FieldAccessorTable to something like ReflectionAccess as it's more than just fields
  • Expose the reflection capabilities via a static property (possibly replacing Descriptor)
  • Change the existing instance property to use explicit interface implementation - you'd usually only want it when we only know we have an IMessage

@anandolee to review (sorry!)

@jskeet jskeet added the c# label Jul 9, 2015
- Added new line at the end of SampleEnum
- Moved GeneratedMessageTest.GetSampleMessage to a new class, SampleMessages, and renamed it to CreateFullTestAllTypes.
@jskeet
Copy link
Contributor Author

jskeet commented Jul 9, 2015

@jtattermusch I've rebased this to include PR #577 (and now that earlier PRs are merged, this looks somewhat smaller).

- 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.
- Add a partial method called by all constructors
- Generate internal classes for descriptor.proto (only)
- Forbid proto2 descriptors except for descriptor.proto
Note that now we need a proto3 version of addressbook.proto. This may affect other platforms, and could do with an overhaul to follow proto3 conventions anyway (e.g. repeated field names). Will need to think about that carefully before merging into master. Raised issue protocolbuffers#565 for this.
- The protos are no longer publicly exposed at all
- Oneof detection now works (as we default to -1, not 0)
- OneofDescriptor exposes the fields in the oneof
- Removed unnecessary code for replacing protos - remnant of extensions
- There's now just the non-generic form of IDescriptor
... and some implementation changes to go with them.
// Commented assertions show an ideal situation - it looks like
// the LinkedList enumerator doesn't throw when you ask for the current entry
// at an inappropriate time; fixing this would be more work than it's worth.
// Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why would fixing it bee more work than it's worth?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because no-one actually relies on this (C# iterator blocks don't do the right thing either), and fixing it in our code (bearing in mind that we can't change LinkedList) would mean keeping a separate field to remember whether or not we're on the first/last element, etc.

@jtattermusch
Copy link
Contributor

So far, I've reviewed the changes around descriptors (which LGTM). I will continue reviewing the reflection part tomorrow.

@jskeet
Copy link
Contributor Author

jskeet commented Jul 10, 2015

Thanks. I'll try to make a few more changes to the JSON formatting so that I can add that PR to be reviewed. Then there's the wrapper type support, which isn't ready yet...

@@ -68,12 +68,12 @@ public static FieldCodec<int> ForSInt32(uint tag)

public static FieldCodec<uint> ForFixed32(uint tag)
{
return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), CodedOutputStream.ComputeFixed32Size, tag);
return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider the magic numbers less readable and more error prone that the previous version that clearly indicated what is the purpose of the number.

@jtattermusch
Copy link
Contributor

The reflection changes also LGTM. Feel free to merge if it speeds you up.

@jskeet
Copy link
Contributor Author

jskeet commented Jul 10, 2015

Thanks, will do.

jskeet added a commit that referenced this pull request Jul 10, 2015
@jskeet jskeet merged commit 94878b3 into protocolbuffers:csharp-experimental Jul 10, 2015
@jskeet jskeet deleted the csharp-reflection branch July 10, 2015 10:24
taoso pushed a commit to taoso/protobuf that referenced this pull request Aug 1, 2018
adellahlou pushed a commit to adellahlou/protobuf that referenced this pull request Apr 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants