diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs index c05cb0853fc8c..771f1f41ba39e 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs @@ -30,8 +30,11 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Reflection; using Google.Protobuf.TestProtos; using NUnit.Framework; +using System.Linq; +using UnitTest.Issues.TestProtos; namespace Google.Protobuf.WellKnownTypes { @@ -148,10 +151,34 @@ public void IsWrongType() Assert.False(any.Is(TestOneof.Descriptor)); } + [Test] public void IsRightType() { var any = Any.Pack(SampleMessages.CreateFullTestAllTypes()); Assert.True(any.Is(TestAllTypes.Descriptor)); } + + [Test] + public void Unpack_TypeRegistry() + { + var messages = new IMessage[] + { + SampleMessages.CreateFullTestAllTypes(), + new TestWellKnownTypes { BoolField = true }, + new MoreString { Data = { "x" } }, + new MoreBytes { Data = ByteString.CopyFromUtf8("xyz") }, + new ReservedNames { Descriptor_ = 10 } + }; + var anyMessages = messages.Select(Any.Pack); + + // The type registry handles the first four of the packed messages, but not the final one. + var registry = TypeRegistry.FromFiles( + UnittestWellKnownTypesReflection.Descriptor, + UnittestProto3Reflection.Descriptor); + var unpacked = anyMessages.Select(any => any.Unpack(registry)).ToList(); + var expected = (IMessage[]) messages.Clone(); + expected[4] = null; + Assert.AreEqual(expected, unpacked); + } } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs index 5e7b6d5a1ee57..cbb08d8b02f0d 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs @@ -120,6 +120,26 @@ public bool Is(MessageDescriptor descriptor) return true; } + /// + /// Attempts to unpack the content of this Any message into one of the message types + /// in the given type registry, based on the type URL. + /// + /// The type registry to consult for messages. + /// The unpacked message, or null if no matching message was found. + public IMessage Unpack(TypeRegistry registry) + { + string typeName = GetTypeName(TypeUrl); + MessageDescriptor descriptor = registry.Find(typeName); + if (descriptor == null) + { + return null; + } + + var message = descriptor.Parser.CreateTemplate(); + message.MergeFrom(Value); + return message; + } + /// /// Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com". ///