1 #region Copyright notice and license 2 3 // Copyright 2015 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #endregion 18 19 using System; 20 using System.Collections.Generic; 21 22 namespace Grpc.Core 23 { 24 /// <summary> 25 /// Stores mapping of methods to server call handlers. 26 /// Normally, the <c>ServerServiceDefinition</c> objects will be created by the <c>BindService</c> factory method 27 /// that is part of the autogenerated code for a protocol buffers service definition. 28 /// </summary> 29 public class ServerServiceDefinition 30 { 31 readonly IReadOnlyList<Action<ServiceBinderBase>> addMethodActions; 32 ServerServiceDefinition(List<Action<ServiceBinderBase>> addMethodActions)33 internal ServerServiceDefinition(List<Action<ServiceBinderBase>> addMethodActions) 34 { 35 this.addMethodActions = addMethodActions.AsReadOnly(); 36 } 37 38 /// <summary> 39 /// Forwards all the previously stored <c>AddMethod</c> calls to the service binder. 40 /// </summary> BindService(ServiceBinderBase serviceBinder)41 internal void BindService(ServiceBinderBase serviceBinder) 42 { 43 foreach (var addMethodAction in addMethodActions) 44 { 45 addMethodAction(serviceBinder); 46 } 47 } 48 49 /// <summary> 50 /// Creates a new builder object for <c>ServerServiceDefinition</c>. 51 /// </summary> 52 /// <returns>The builder object.</returns> CreateBuilder()53 public static Builder CreateBuilder() 54 { 55 return new Builder(); 56 } 57 58 /// <summary> 59 /// Builder class for <see cref="ServerServiceDefinition"/>. 60 /// </summary> 61 public class Builder 62 { 63 // to maintain legacy behavior, we need to detect duplicate keys and throw the same exception as before 64 readonly Dictionary<string, object> duplicateDetector = new Dictionary<string, object>(); 65 // for each AddMethod call, we store an action that will later register the method and handler with ServiceBinderBase 66 readonly List<Action<ServiceBinderBase>> addMethodActions = new List<Action<ServiceBinderBase>>(); 67 68 /// <summary> 69 /// Creates a new instance of builder. 70 /// </summary> Builder()71 public Builder() 72 { 73 } 74 75 /// <summary> 76 /// Adds a definition for a single request - single response method. 77 /// </summary> 78 /// <typeparam name="TRequest">The request message class.</typeparam> 79 /// <typeparam name="TResponse">The response message class.</typeparam> 80 /// <param name="method">The method.</param> 81 /// <param name="handler">The method handler.</param> 82 /// <returns>This builder instance.</returns> 83 public Builder AddMethod<TRequest, TResponse>( 84 Method<TRequest, TResponse> method, 85 UnaryServerMethod<TRequest, TResponse> handler) 86 where TRequest : class 87 where TResponse : class 88 { duplicateDetector.Add(method.FullName, null)89 duplicateDetector.Add(method.FullName, null); addMethodActions.Addnull90 addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); 91 return this; 92 } 93 94 /// <summary> 95 /// Adds a definition for a client streaming method. 96 /// </summary> 97 /// <typeparam name="TRequest">The request message class.</typeparam> 98 /// <typeparam name="TResponse">The response message class.</typeparam> 99 /// <param name="method">The method.</param> 100 /// <param name="handler">The method handler.</param> 101 /// <returns>This builder instance.</returns> 102 public Builder AddMethod<TRequest, TResponse>( 103 Method<TRequest, TResponse> method, 104 ClientStreamingServerMethod<TRequest, TResponse> handler) 105 where TRequest : class 106 where TResponse : class 107 { duplicateDetector.Add(method.FullName, null)108 duplicateDetector.Add(method.FullName, null); addMethodActions.Addnull109 addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); 110 return this; 111 } 112 113 /// <summary> 114 /// Adds a definition for a server streaming method. 115 /// </summary> 116 /// <typeparam name="TRequest">The request message class.</typeparam> 117 /// <typeparam name="TResponse">The response message class.</typeparam> 118 /// <param name="method">The method.</param> 119 /// <param name="handler">The method handler.</param> 120 /// <returns>This builder instance.</returns> 121 public Builder AddMethod<TRequest, TResponse>( 122 Method<TRequest, TResponse> method, 123 ServerStreamingServerMethod<TRequest, TResponse> handler) 124 where TRequest : class 125 where TResponse : class 126 { duplicateDetector.Add(method.FullName, null)127 duplicateDetector.Add(method.FullName, null); addMethodActions.Addnull128 addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); 129 return this; 130 } 131 132 /// <summary> 133 /// Adds a definition for a bidirectional streaming method. 134 /// </summary> 135 /// <typeparam name="TRequest">The request message class.</typeparam> 136 /// <typeparam name="TResponse">The response message class.</typeparam> 137 /// <param name="method">The method.</param> 138 /// <param name="handler">The method handler.</param> 139 /// <returns>This builder instance.</returns> 140 public Builder AddMethod<TRequest, TResponse>( 141 Method<TRequest, TResponse> method, 142 DuplexStreamingServerMethod<TRequest, TResponse> handler) 143 where TRequest : class 144 where TResponse : class 145 { duplicateDetector.Add(method.FullName, null)146 duplicateDetector.Add(method.FullName, null); addMethodActions.Addnull147 addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); 148 return this; 149 } 150 151 /// <summary> 152 /// Creates an immutable <c>ServerServiceDefinition</c> from this builder. 153 /// </summary> 154 /// <returns>The <c>ServerServiceDefinition</c> object.</returns> Build()155 public ServerServiceDefinition Build() 156 { 157 return new ServerServiceDefinition(addMethodActions); 158 } 159 } 160 } 161 } 162