@@ -24,57 +24,77 @@ are observed and respected
2424 /// <summary>
2525 /// Initiate a bind operation, causing all service methods to be crawled for the provided type
2626 /// </summary>
27- public int Bind < TService > ( object state , BinderConfiguration ? binderConfiguration = null , TService ? service = null )
27+ public int Bind < TService > ( object state , BinderConfiguration ? binderConfiguration = null ,
28+ TService ? service = null )
2829 where TService : class
2930 => Bind ( state , typeof ( TService ) , binderConfiguration , service ) ;
3031
3132 /// <summary>
3233 /// Initiate a bind operation, causing all service methods to be crawled for the provided type
3334 /// </summary>
34- public int Bind ( object state , Type serviceType , BinderConfiguration ? binderConfiguration = null , object ? service = null )
35+ public int Bind ( object state , Type serviceType , BinderConfiguration ? binderConfiguration = null ,
36+ object ? service = null )
3537 {
3638 int totalCount = 0 ;
3739 object ? [ ] ? argsBuffer = null ;
3840 Type [ ] typesBuffer = Array . Empty < Type > ( ) ;
39- string ? serviceName ;
40- if ( binderConfiguration == null ) binderConfiguration = BinderConfiguration . Default ;
41- var serviceContracts = typeof ( IGrpcService ) . IsAssignableFrom ( serviceType )
42- ? new HashSet < Type > { serviceType }
41+ binderConfiguration ??= BinderConfiguration . Default ;
42+ var potentialServiceContracts = typeof ( IGrpcService ) . IsAssignableFrom ( serviceType )
43+ ? new HashSet < Type > { serviceType }
4344 : ContractOperation . ExpandInterfaces ( serviceType ) ;
4445
4546 bool serviceImplSimplifiedExceptions = serviceType . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) ) ;
46- foreach ( var serviceContract in serviceContracts )
47+ foreach ( var potentialServiceContract in potentialServiceContracts )
4748 {
48- if ( ! binderConfiguration . Binder . IsServiceContract ( serviceContract , out serviceName ) ) continue ;
49+ if ( ! binderConfiguration . Binder . IsServiceContract ( potentialServiceContract , out var serviceName ) ) continue ;
50+
51+ // now that we know it is a service contract type for sure
52+ var serviceContract = potentialServiceContract ;
53+
54+ var typesToBeIncludedInMethodsBinding =
55+ ContractOperation . ExpandWithInterfacesMarkedAsSubService ( binderConfiguration . Binder , serviceContract ) ;
56+
57+ // Per service contract, we will collect all the methods of sub-service interfaces
58+ // and bind them as they were defined in the service contract itself.
59+ // (their binding key will be based on the service contract and not based on the base-interfaces).
4960
50- var serviceContractSimplifiedExceptions = serviceImplSimplifiedExceptions || serviceContract . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) ) ;
5161 int svcOpCount = 0 ;
52- var bindCtx = new ServiceBindContext ( serviceContract , serviceType , state , binderConfiguration . Binder ) ;
53- foreach ( var op in ContractOperation . FindOperations ( binderConfiguration , serviceContract , this ) )
62+ foreach ( var typeToBindItsMethods in typesToBeIncludedInMethodsBinding )
5463 {
55- if ( ServerInvokerLookup . TryGetValue ( op . MethodType , op . Context , op . Arg , op . Result , op . Void , out var invoker )
56- && AddMethod ( op . From , op . To , op . Name , op . Method , op . MethodType , invoker , bindCtx ,
57- serviceContractSimplifiedExceptions || op . Method . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) )
58- ) )
64+ var serviceContractSimplifiedExceptions = serviceImplSimplifiedExceptions ||
65+ typeToBindItsMethods . IsDefined (
66+ typeof ( SimpleRpcExceptionsAttribute ) ) ;
67+ var bindCtx = new ServiceBindContext ( serviceContract , serviceType , state , binderConfiguration . Binder ) ;
68+ foreach ( var op in ContractOperation . FindOperations ( binderConfiguration , typeToBindItsMethods , this ) )
5969 {
60- // yay!
61- totalCount ++ ;
62- svcOpCount ++ ;
70+ if ( ServerInvokerLookup . TryGetValue ( op . MethodType , op . Context , op . Arg , op . Result , op . Void , out var invoker )
71+ && AddMethod ( serviceName , op . From , op . To , op . Name , op . Method , op . MethodType , invoker , bindCtx ,
72+ serviceContractSimplifiedExceptions || op . Method . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) )
73+ ) )
74+ {
75+ // yay!
76+ totalCount ++ ;
77+ svcOpCount ++ ;
78+ }
6379 }
6480 }
81+
6582 OnServiceBound ( state , serviceName ! , serviceType , serviceContract , svcOpCount ) ;
6683 }
84+
6785 return totalCount ;
6886
69- bool AddMethod ( Type @in , Type @out , string on , MethodInfo m , MethodType t ,
70- Func < MethodInfo , ParameterExpression [ ] , Expression > ? invoker , ServiceBindContext bindContext , bool simplifiedExceptionHandling )
87+ bool AddMethod ( string ? serviceName , Type @in , Type @out , string on , MethodInfo m , MethodType t ,
88+ Func < MethodInfo , ParameterExpression [ ] , Expression > ? invoker , ServiceBindContext bindContext ,
89+ bool simplifiedExceptionHandling )
7190 {
7291 try
7392 {
7493 if ( typesBuffer . Length == 0 )
7594 {
76- typesBuffer = new Type [ ] { serviceType , typeof ( void ) , typeof ( void ) } ;
95+ typesBuffer = new Type [ ] { serviceType , typeof ( void ) , typeof ( void ) } ;
7796 }
97+
7898 typesBuffer [ 1 ] = @in ;
7999 typesBuffer [ 2 ] = @out ;
80100
@@ -84,6 +104,7 @@ bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t,
84104 argsBuffer [ 6 ] = binderConfiguration ! . MarshallerCache ;
85105 argsBuffer [ 7 ] = service is null ? null : Expression . Constant ( service , serviceType ) ;
86106 }
107+
87108 argsBuffer [ 0 ] = serviceName ;
88109 argsBuffer [ 1 ] = on ;
89110 argsBuffer [ 2 ] = m ;
@@ -93,7 +114,7 @@ bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t,
93114 // 6, 7 set during array initialization
94115 argsBuffer [ 8 ] = simplifiedExceptionHandling ;
95116
96- return ( bool ) s_addMethod . MakeGenericMethod ( typesBuffer ) . Invoke ( this , argsBuffer ) ! ;
117+ return ( bool ) s_addMethod . MakeGenericMethod ( typesBuffer ) . Invoke ( this , argsBuffer ) ! ;
97118 }
98119 catch ( Exception fail )
99120 {
@@ -128,7 +149,8 @@ protected readonly struct MethodStub<TService>
128149 /// </summary>
129150 public MethodInfo Method { get ; }
130151
131- internal MethodStub ( Func < MethodInfo , Expression [ ] , Expression > ? invoker , MethodInfo method , ConstantExpression ? service , bool simpleExceptionHandling )
152+ internal MethodStub ( Func < MethodInfo , Expression [ ] , Expression > ? invoker , MethodInfo method ,
153+ ConstantExpression ? service , bool simpleExceptionHandling )
132154 {
133155 _simpleExceptionHandling = simpleExceptionHandling ;
134156 _invoker = invoker ;
@@ -158,7 +180,7 @@ public TDelegate CreateDelegate<TDelegate>()
158180 else
159181 {
160182 // basic - direct call
161- return ( TDelegate ) Delegate . CreateDelegate ( typeof ( TDelegate ) , _service , Method ) ;
183+ return ( TDelegate ) Delegate . CreateDelegate ( typeof ( TDelegate ) , _service , Method ) ;
162184 }
163185 }
164186 else
@@ -167,7 +189,8 @@ public TDelegate CreateDelegate<TDelegate>()
167189
168190 Expression [ ] mapArgs ;
169191 if ( _service is null )
170- { // if no service object, then the service is part of the signature, i.e. (svc, req) => svc.Blah();
192+ {
193+ // if no service object, then the service is part of the signature, i.e. (svc, req) => svc.Blah();
171194 mapArgs = lambdaArgs ;
172195 }
173196 else
@@ -184,6 +207,7 @@ public TDelegate CreateDelegate<TDelegate>()
184207 {
185208 body = ApplySimpleExceptionHandling ( body ) ;
186209 }
210+
187211 var lambda = Expression . Lambda < TDelegate > ( body , lambdaArgs ) ;
188212
189213 return lambda . Compile ( ) ;
@@ -199,17 +223,19 @@ static Expression ApplySimpleExceptionHandling(Expression body)
199223 }
200224 else if ( type . IsGenericType && type . GetGenericTypeDefinition ( ) == typeof ( Task < > ) )
201225 {
202- body = Expression . Call ( s_ReshapeWithSimpleExceptionHandling [ 1 ] . MakeGenericMethod ( type . GetGenericArguments ( ) ) , body ) ;
226+ body = Expression . Call (
227+ s_ReshapeWithSimpleExceptionHandling [ 1 ] . MakeGenericMethod ( type . GetGenericArguments ( ) ) , body ) ;
203228 }
229+
204230 return body ;
205231 }
206232 }
207233
208234#pragma warning disable CS0618
209235 private static readonly Dictionary < int , MethodInfo > s_ReshapeWithSimpleExceptionHandling =
210236 ( from method in typeof ( Reshape ) . GetMethods ( BindingFlags . Public | BindingFlags . Static )
211- where method . Name is nameof ( Reshape . WithSimpleExceptionHandling )
212- select method )
237+ where method . Name is nameof ( Reshape . WithSimpleExceptionHandling )
238+ select method )
213239 . ToDictionary ( method => method . IsGenericMethodDefinition ? method . GetGenericArguments ( ) . Length : 0 ) ;
214240#pragma warning restore CS0618
215241
@@ -222,7 +248,8 @@ private bool AddMethod<TService, TRequest, TResponse>(
222248 where TRequest : class
223249 where TResponse : class
224250 {
225- var grpcMethod = new Method < TRequest , TResponse > ( methodType , serviceName , operationName , marshallerCache . GetMarshaller < TRequest > ( ) , marshallerCache . GetMarshaller < TResponse > ( ) ) ;
251+ var grpcMethod = new Method < TRequest , TResponse > ( methodType , serviceName , operationName ,
252+ marshallerCache . GetMarshaller < TRequest > ( ) , marshallerCache . GetMarshaller < TResponse > ( ) ) ;
226253 var stub = new MethodStub < TService > ( invoker , method , service , simplfiedExceptionHandling ) ;
227254 try
228255 {
@@ -235,13 +262,11 @@ private bool AddMethod<TService, TRequest, TResponse>(
235262 OnError ( ex . Message ) ;
236263 return false ;
237264 }
238-
239265 }
240266
241267 void IBindContext . LogWarning ( string message , object ? [ ] ? args ) => OnWarn ( message , args ) ;
242268 void IBindContext . LogError ( string message , object ? [ ] ? args ) => OnError ( message , args ) ;
243269
244- /// <summary>
245270 /// Describes the relationship between a service contract and a service definition
246271 /// </summary>
247272 protected internal sealed class ServiceBindContext
@@ -283,4 +308,4 @@ public IList<object> GetMetadata(MethodInfo method)
283308 => ServiceBinder . GetMetadata ( method , ContractType , ServiceType ) ;
284309 }
285310 }
286- }
311+ }
0 commit comments