Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
d6202a9b
Commit
d6202a9b
authored
9 years ago
by
Jon Skeet
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #994 from jskeet/type-registry
Added the type registry in advance of implementing Any support.
parents
956a770a
f7e43c6f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
279 additions
and
0 deletions
+279
-0
Google.Protobuf.Test.csproj
csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
+1
-0
TypeRegistryTest.cs
...p/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs
+94
-0
Google.Protobuf.csproj
csharp/src/Google.Protobuf/Google.Protobuf.csproj
+1
-0
TypeRegistry.cs
csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs
+183
-0
No files found.
csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
View file @
d6202a9b
...
...
@@ -99,6 +99,7 @@
<Compile
Include=
"JsonTokenizerTest.cs"
/>
<Compile
Include=
"Reflection\DescriptorsTest.cs"
/>
<Compile
Include=
"Reflection\FieldAccessTest.cs"
/>
<Compile
Include=
"Reflection\TypeRegistryTest.cs"
/>
<Compile
Include=
"SampleEnum.cs"
/>
<Compile
Include=
"SampleMessages.cs"
/>
<Compile
Include=
"TestProtos\MapUnittestProto3.cs"
/>
...
...
This diff is collapsed.
Click to expand it.
csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs
0 → 100644
View file @
d6202a9b
#
region
Copyright
notice
and
license
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// 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.
#endregion
using
Google.Protobuf.TestProtos
;
using
Google.Protobuf.WellKnownTypes
;
using
NUnit.Framework
;
namespace
Google.Protobuf.Reflection
{
public
class
TypeRegistryTest
{
// Most of our tests use messages. Simple test that we really can use files...
[
Test
]
public
void
CreateWithFileDescriptor
()
{
var
registry
=
TypeRegistry
.
FromFiles
(
DurationReflection
.
Descriptor
,
StructReflection
.
Descriptor
);
AssertDescriptorPresent
(
registry
,
Duration
.
Descriptor
);
AssertDescriptorPresent
(
registry
,
ListValue
.
Descriptor
);
AssertDescriptorAbsent
(
registry
,
Timestamp
.
Descriptor
);
}
[
Test
]
public
void
TypesFromSameFile
()
{
// Just for kicks, let's start with a nested type
var
registry
=
TypeRegistry
.
FromMessages
(
TestAllTypes
.
Types
.
NestedMessage
.
Descriptor
);
// Top-level...
AssertDescriptorPresent
(
registry
,
TestFieldOrderings
.
Descriptor
);
// ... and nested (not the same as the original NestedMessage!)
AssertDescriptorPresent
(
registry
,
TestFieldOrderings
.
Types
.
NestedMessage
.
Descriptor
);
}
[
Test
]
public
void
DependenciesAreIncluded
()
{
var
registry
=
TypeRegistry
.
FromMessages
(
TestAllTypes
.
Descriptor
);
// Direct dependencies
AssertDescriptorPresent
(
registry
,
ImportMessage
.
Descriptor
);
// Public dependencies
AssertDescriptorPresent
(
registry
,
PublicImportMessage
.
Descriptor
);
}
[
Test
]
public
void
DuplicateFiles
()
{
// Duplicates via dependencies and simply via repetition
var
registry
=
TypeRegistry
.
FromFiles
(
UnittestProto3Reflection
.
Descriptor
,
UnittestImportProto3Reflection
.
Descriptor
,
TimestampReflection
.
Descriptor
,
TimestampReflection
.
Descriptor
);
AssertDescriptorPresent
(
registry
,
TestAllTypes
.
Descriptor
);
AssertDescriptorPresent
(
registry
,
ImportMessage
.
Descriptor
);
AssertDescriptorPresent
(
registry
,
Timestamp
.
Descriptor
);
}
private
static
void
AssertDescriptorPresent
(
TypeRegistry
registry
,
MessageDescriptor
descriptor
)
{
Assert
.
AreSame
(
descriptor
,
registry
.
Find
(
descriptor
.
FullName
));
}
private
static
void
AssertDescriptorAbsent
(
TypeRegistry
registry
,
MessageDescriptor
descriptor
)
{
Assert
.
IsNull
(
registry
.
Find
(
descriptor
.
FullName
));
}
}
}
This diff is collapsed.
Click to expand it.
csharp/src/Google.Protobuf/Google.Protobuf.csproj
View file @
d6202a9b
...
...
@@ -121,6 +121,7 @@
<Compile
Include=
"Reflection\ServiceDescriptor.cs"
/>
<Compile
Include=
"Reflection\SingleFieldAccessor.cs"
/>
<Compile
Include=
"Preconditions.cs"
/>
<Compile
Include=
"Reflection\TypeRegistry.cs"
/>
<Compile
Include=
"WellKnownTypes\Any.cs"
/>
<Compile
Include=
"WellKnownTypes\AnyPartial.cs"
/>
<Compile
Include=
"WellKnownTypes\Api.cs"
/>
...
...
This diff is collapsed.
Click to expand it.
csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs
0 → 100644
View file @
d6202a9b
#
region
Copyright
notice
and
license
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// 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.
#endregion
using
System.Collections.Generic
;
using
System.Linq
;
namespace
Google.Protobuf.Reflection
{
/// <summary>
/// An immutable registry of types which can be looked up by their full name.
/// </summary>
public
sealed
class
TypeRegistry
{
/// <summary>
/// An empty type registry, containing no types.
/// </summary>
public
static
TypeRegistry
Empty
{
get
;
}
=
new
TypeRegistry
(
new
Dictionary
<
string
,
MessageDescriptor
>());
private
readonly
Dictionary
<
string
,
MessageDescriptor
>
fullNameToMessageMap
;
private
TypeRegistry
(
Dictionary
<
string
,
MessageDescriptor
>
fullNameToMessageMap
)
{
this
.
fullNameToMessageMap
=
fullNameToMessageMap
;
}
/// <summary>
/// Attempts to find a message descriptor by its full name.
/// </summary>
/// <param name="fullName">The full name of the message, which is the dot-separated
/// combination of package, containing messages and message name</param>
/// <returns>The message descriptor corresponding to <paramref name="fullName"/> or null
/// if there is no such message descriptor.</returns>
public
MessageDescriptor
Find
(
string
fullName
)
{
MessageDescriptor
ret
;
// Ignore the return value as ret will end up with the right value either way.
fullNameToMessageMap
.
TryGetValue
(
fullName
,
out
ret
);
return
ret
;
}
/// <summary>
/// Creates a type registry from the specified set of file descriptors.
/// </summary>
/// <remarks>
/// This is a convenience overload for <see cref="FromFiles(IEnumerable{FileDescriptor})"/>
/// to allow calls such as <c>TypeRegistry.FromFiles(descriptor1, descriptor2)</c>.
/// </remarks>
/// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param>
/// <returns>A type registry for the given files.</returns>
public
static
TypeRegistry
FromFiles
(
params
FileDescriptor
[]
fileDescriptors
)
{
return
FromFiles
((
IEnumerable
<
FileDescriptor
>)
fileDescriptors
);
}
/// <summary>
/// Creates a type registry from the specified set of file descriptors.
/// </summary>
/// <remarks>
/// All message types within all the specified files are added to the registry, and
/// the dependencies of the specified files are also added, recursively.
/// </remarks>
/// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param>
/// <returns>A type registry for the given files.</returns>
public
static
TypeRegistry
FromFiles
(
IEnumerable
<
FileDescriptor
>
fileDescriptors
)
{
Preconditions
.
CheckNotNull
(
fileDescriptors
,
nameof
(
fileDescriptors
));
var
builder
=
new
Builder
();
foreach
(
var
file
in
fileDescriptors
)
{
builder
.
AddFile
(
file
);
}
return
builder
.
Build
();
}
/// <summary>
/// Creates a type registry from the file descriptor parents of the specified set of message descriptors.
/// </summary>
/// <remarks>
/// This is a convenience overload for <see cref="FromMessages(IEnumerable{MessageDescriptor})"/>
/// to allow calls such as <c>TypeRegistry.FromFiles(descriptor1, descriptor2)</c>.
/// </remarks>
/// <param name="messageDescriptors">The set of message descriptors to use to identify file descriptors to include in the registry.
/// Must not contain null values.</param>
/// <returns>A type registry for the given files.</returns>
public
static
TypeRegistry
FromMessages
(
params
MessageDescriptor
[]
messageDescriptors
)
{
return
FromMessages
((
IEnumerable
<
MessageDescriptor
>)
messageDescriptors
);
}
/// <summary>
/// Creates a type registry from the file descriptor parents of the specified set of message descriptors.
/// </summary>
/// <remarks>
/// The specified message descriptors are only used to identify their file descriptors; the returned registry
/// contains all the types within the file descriptors which contain the specified message descriptors (and
/// the dependencies of those files), not just the specified messages.
/// </remarks>
/// <param name="messageDescriptors">The set of message descriptors to use to identify file descriptors to include in the registry.
/// Must not contain null values.</param>
/// <returns>A type registry for the given files.</returns>
public
static
TypeRegistry
FromMessages
(
IEnumerable
<
MessageDescriptor
>
messageDescriptors
)
{
Preconditions
.
CheckNotNull
(
messageDescriptors
,
nameof
(
messageDescriptors
));
return
FromFiles
(
messageDescriptors
.
Select
(
md
=>
md
.
File
));
}
/// <summary>
/// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls.
/// </summary>
private
class
Builder
{
private
readonly
Dictionary
<
string
,
MessageDescriptor
>
types
;
private
readonly
HashSet
<
string
>
fileDescriptorNames
;
internal
Builder
()
{
types
=
new
Dictionary
<
string
,
MessageDescriptor
>();
fileDescriptorNames
=
new
HashSet
<
string
>();
}
internal
void
AddFile
(
FileDescriptor
fileDescriptor
)
{
if
(!
fileDescriptorNames
.
Add
(
fileDescriptor
.
Name
))
{
return
;
}
foreach
(
var
dependency
in
fileDescriptor
.
Dependencies
)
{
AddFile
(
dependency
);
}
foreach
(
var
message
in
fileDescriptor
.
MessageTypes
)
{
AddMessage
(
message
);
}
}
private
void
AddMessage
(
MessageDescriptor
messageDescriptor
)
{
foreach
(
var
nestedType
in
messageDescriptor
.
NestedTypes
)
{
AddMessage
(
nestedType
);
}
// This will overwrite any previous entry. Given that each file should
// only be added once, this could be a problem such as package A.B with type C,
// and package A with type B.C... it's unclear what we should do in that case.
types
[
messageDescriptor
.
FullName
]
=
messageDescriptor
;
}
internal
TypeRegistry
Build
()
{
return
new
TypeRegistry
(
types
);
}
}
}
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment