• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2008 Google Inc.  All rights reserved.
4 //
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file or at
7 // https://developers.google.com/open-source/licenses/bsd
8 #endregion
9 
10 using Google.Protobuf.Collections;
11 using System;
12 
13 namespace Google.Protobuf.Reflection
14 {
15     /// <summary>
16     /// Describes a single method in a service.
17     /// </summary>
18     public sealed class MethodDescriptor : DescriptorBase
19     {
20         /// <value>
21         /// The service this method belongs to.
22         /// </value>
23         public ServiceDescriptor Service { get; }
24 
25         /// <value>
26         /// The method's input type.
27         /// </value>
28         public MessageDescriptor InputType { get; private set; }
29 
30         /// <value>
31         /// The method's input type.
32         /// </value>
33         public MessageDescriptor OutputType { get; private set; }
34 
35         /// <value>
36         /// Indicates if client streams multiple requests.
37         /// </value>
38         public bool IsClientStreaming => Proto.ClientStreaming;
39 
40         /// <value>
41         /// Indicates if server streams multiple responses.
42         /// </value>
43         public bool IsServerStreaming => Proto.ServerStreaming;
44 
45         /// <summary>
46         /// The (possibly empty) set of custom options for this method.
47         /// </summary>
48         [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
49         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
50 
51         /// <summary>
52         /// The <c>MethodOptions</c>, defined in <c>descriptor.proto</c>.
53         /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
54         /// Custom options can be retrieved as extensions of the returned message.
55         /// NOTE: A defensive copy is created each time this property is retrieved.
56         /// </summary>
GetOptions()57         public MethodOptions GetOptions()
58         {
59             var clone = Proto.Options?.Clone();
60             if (clone is null)
61             {
62                 return null;
63             }
64             // Clients should be using feature accessor methods, not accessing features on the
65             // options proto.
66             clone.Features = null;
67             return clone;
68         }
69 
70         /// <summary>
71         /// Gets a single value method option for this descriptor
72         /// </summary>
73         [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
GetOption(Extension<MethodOptions, T> extension)74         public T GetOption<T>(Extension<MethodOptions, T> extension)
75         {
76             var value = Proto.Options.GetExtension(extension);
77             return value is IDeepCloneable<T> c ? c.Clone() : value;
78         }
79 
80         /// <summary>
81         /// Gets a repeated value method option for this descriptor
82         /// </summary>
83         [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
GetOption(RepeatedExtension<MethodOptions, T> extension)84         public RepeatedField<T> GetOption<T>(RepeatedExtension<MethodOptions, T> extension)
85         {
86             return Proto.Options.GetExtension(extension).Clone();
87         }
88 
MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file, ServiceDescriptor parent, int index)89         internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file,
90                                   ServiceDescriptor parent, int index)
91             : base(file, parent.FullName + "." + proto.Name, index, parent.Features.MergedWith(proto.Options?.Features))
92         {
93             Proto = proto;
94             Service = parent;
95             file.DescriptorPool.AddSymbol(this);
96         }
97 
98         internal MethodDescriptorProto Proto { get; private set; }
99 
100         /// <summary>
101         /// Returns a clone of the underlying <see cref="MethodDescriptorProto"/> describing this method.
102         /// Note that a copy is taken every time this method is called, so clients using it frequently
103         /// (and not modifying it) may want to cache the returned value.
104         /// </summary>
105         /// <returns>A protobuf representation of this method descriptor.</returns>
ToProto()106         public MethodDescriptorProto ToProto() => Proto.Clone();
107 
108         /// <summary>
109         /// The brief name of the descriptor's target.
110         /// </summary>
111         public override string Name => Proto.Name;
112 
CrossLink()113         internal void CrossLink()
114         {
115             IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this);
116             if (lookup is not MessageDescriptor inputType)
117             {
118                 throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type.");
119             }
120             InputType = inputType;
121 
122             lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this);
123             if (lookup is not MessageDescriptor outputType)
124             {
125                 throw new DescriptorValidationException(this, "\"" + Proto.OutputType + "\" is not a message type.");
126             }
127             OutputType = outputType;
128         }
129     }
130 }
131