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 using System.Collections.Generic; 13 14 namespace Google.Protobuf.Reflection 15 { 16 /// <summary> 17 /// Describes a service type. 18 /// </summary> 19 public sealed class ServiceDescriptor : DescriptorBase 20 { ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)21 internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index) 22 : base(file, file.ComputeFullName(null, proto.Name), index, file.Features.MergedWith(proto.Options?.Features)) 23 { 24 Proto = proto; 25 Methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method, 26 (method, i) => new MethodDescriptor(method, file, this, i)); 27 28 file.DescriptorPool.AddSymbol(this); 29 } 30 31 /// <summary> 32 /// The brief name of the descriptor's target. 33 /// </summary> 34 public override string Name => Proto.Name; 35 GetNestedDescriptorListForField(int fieldNumber)36 internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) => 37 fieldNumber switch 38 { 39 ServiceDescriptorProto.MethodFieldNumber => (IReadOnlyList<DescriptorBase>)Methods, 40 _ => null, 41 }; 42 43 internal ServiceDescriptorProto Proto { get; } 44 45 /// <summary> 46 /// Returns a clone of the underlying <see cref="ServiceDescriptorProto"/> describing this service. 47 /// Note that a copy is taken every time this method is called, so clients using it frequently 48 /// (and not modifying it) may want to cache the returned value. 49 /// </summary> 50 /// <returns>A protobuf representation of this service descriptor.</returns> ToProto()51 public ServiceDescriptorProto ToProto() => Proto.Clone(); 52 53 /// <value> 54 /// An unmodifiable list of methods in this service. 55 /// </value> 56 public IList<MethodDescriptor> Methods { get; } 57 58 /// <summary> 59 /// Finds a method by name. 60 /// </summary> 61 /// <param name="name">The unqualified name of the method (e.g. "Foo").</param> 62 /// <returns>The method's descriptor, or null if not found.</returns> FindMethodByName(string name)63 public MethodDescriptor FindMethodByName(string name) => 64 File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name); 65 66 /// <summary> 67 /// The (possibly empty) set of custom options for this service. 68 /// </summary> 69 [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")] 70 public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber); 71 72 /// <summary> 73 /// The <c>ServiceOptions</c>, defined in <c>descriptor.proto</c>. 74 /// If the options message is not present (i.e. there are no options), <c>null</c> is returned. 75 /// Custom options can be retrieved as extensions of the returned message. 76 /// NOTE: A defensive copy is created each time this property is retrieved. 77 /// </summary> GetOptions()78 public ServiceOptions GetOptions() 79 { 80 var clone = Proto.Options?.Clone(); 81 if (clone is null) 82 { 83 return null; 84 } 85 // Clients should be using feature accessor methods, not accessing features on the 86 // options proto. 87 clone.Features = null; 88 return clone; 89 } 90 91 /// <summary> 92 /// Gets a single value service option for this descriptor 93 /// </summary> 94 [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] GetOption(Extension<ServiceOptions, T> extension)95 public T GetOption<T>(Extension<ServiceOptions, T> extension) 96 { 97 var value = Proto.Options.GetExtension(extension); 98 return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value; 99 } 100 101 /// <summary> 102 /// Gets a repeated value service option for this descriptor 103 /// </summary> 104 [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] GetOption(RepeatedExtension<ServiceOptions, T> extension)105 public RepeatedField<T> GetOption<T>(RepeatedExtension<ServiceOptions, T> extension) 106 { 107 return Proto.Options.GetExtension(extension).Clone(); 108 } 109 CrossLink()110 internal void CrossLink() 111 { 112 foreach (MethodDescriptor method in Methods) 113 { 114 method.CrossLink(); 115 } 116 } 117 } 118 } 119