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
Nov 22, 2015
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"
/>
...
...
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
));
}
}
}
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"
/>
...
...
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
);
}
}
}
}
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