@@ -24,57 +24,74 @@ are observed and respected
24
24
/// <summary>
25
25
/// Initiate a bind operation, causing all service methods to be crawled for the provided type
26
26
/// </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 )
28
29
where TService : class
29
30
=> Bind ( state , typeof ( TService ) , binderConfiguration , service ) ;
30
31
31
32
/// <summary>
32
33
/// Initiate a bind operation, causing all service methods to be crawled for the provided type
33
34
/// </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 )
35
37
{
36
38
int totalCount = 0 ;
37
39
object ? [ ] ? argsBuffer = null ;
38
40
Type [ ] typesBuffer = Array . Empty < Type > ( ) ;
39
- string ? serviceName ;
40
41
if ( binderConfiguration == null ) binderConfiguration = BinderConfiguration . Default ;
41
42
var serviceContracts = typeof ( IGrpcService ) . IsAssignableFrom ( serviceType )
42
- ? new HashSet < Type > { serviceType }
43
+ ? new HashSet < Type > { serviceType }
43
44
: ContractOperation . ExpandInterfaces ( serviceType ) ;
44
45
45
46
bool serviceImplSimplifiedExceptions = serviceType . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) ) ;
46
47
foreach ( var serviceContract in serviceContracts )
47
48
{
48
- if ( ! binderConfiguration . Binder . IsServiceContract ( serviceContract , out serviceName ) ) continue ;
49
+ if ( ! binderConfiguration . Binder . IsServiceContract ( serviceContract , out var serviceName ) ) continue ;
50
+
51
+ var typesToBeIncludedInMethodsBinding =
52
+ ContractOperation . ExpandWithInterfacesMarkedAsServiceInheritable ( serviceContract ) ;
53
+
54
+ // Per service contract, we will collect all the methods of inherited interfaces
55
+ // and bind them as they were defined in the service contract itself.
56
+ // (their binding key will be based on the service contract and not based on the base-interfaces).
49
57
50
- var serviceContractSimplifiedExceptions = serviceImplSimplifiedExceptions || serviceContract . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) ) ;
51
58
int svcOpCount = 0 ;
52
- var bindCtx = new ServiceBindContext ( serviceContract , serviceType , state , binderConfiguration . Binder ) ;
53
- foreach ( var op in ContractOperation . FindOperations ( binderConfiguration , serviceContract , this ) )
59
+ foreach ( var typeToBindItsMethods in typesToBeIncludedInMethodsBinding )
54
60
{
55
- if ( ServerInvokerLookup . TryGetValue ( op . MethodType , op . Context , 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
- ) )
61
+ var serviceContractSimplifiedExceptions = serviceImplSimplifiedExceptions ||
62
+ typeToBindItsMethods . IsDefined (
63
+ typeof ( SimpleRpcExceptionsAttribute ) ) ;
64
+ var bindCtx = new ServiceBindContext ( serviceContract , serviceType , state , binderConfiguration . Binder ) ;
65
+ foreach ( var op in ContractOperation . FindOperations ( binderConfiguration , typeToBindItsMethods , this ) )
59
66
{
60
- // yay!
61
- totalCount ++ ;
62
- svcOpCount ++ ;
67
+ if ( ServerInvokerLookup . TryGetValue ( op . MethodType , op . Context , op . Result , op . Void , out var invoker )
68
+ && AddMethod ( serviceName , op . From , op . To , op . Name , op . Method , op . MethodType , invoker , bindCtx ,
69
+ serviceContractSimplifiedExceptions || op . Method . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) )
70
+ ) )
71
+ {
72
+ // yay!
73
+ totalCount ++ ;
74
+ svcOpCount ++ ;
75
+ }
63
76
}
64
77
}
78
+
65
79
OnServiceBound ( state , serviceName ! , serviceType , serviceContract , svcOpCount ) ;
66
80
}
81
+
67
82
return totalCount ;
68
83
69
- bool AddMethod ( Type @in , Type @out , string on , MethodInfo m , MethodType t ,
70
- Func < MethodInfo , ParameterExpression [ ] , Expression > ? invoker , ServiceBindContext bindContext , bool simplifiedExceptionHandling )
84
+ bool AddMethod ( string ? serviceName , Type @in , Type @out , string on , MethodInfo m , MethodType t ,
85
+ Func < MethodInfo , ParameterExpression [ ] , Expression > ? invoker , ServiceBindContext bindContext ,
86
+ bool simplifiedExceptionHandling )
71
87
{
72
88
try
73
89
{
74
90
if ( typesBuffer . Length == 0 )
75
91
{
76
- typesBuffer = new Type [ ] { serviceType , typeof ( void ) , typeof ( void ) } ;
92
+ typesBuffer = new Type [ ] { serviceType , typeof ( void ) , typeof ( void ) } ;
77
93
}
94
+
78
95
typesBuffer [ 1 ] = @in ;
79
96
typesBuffer [ 2 ] = @out ;
80
97
@@ -84,6 +101,7 @@ bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t,
84
101
argsBuffer [ 6 ] = binderConfiguration ! . MarshallerCache ;
85
102
argsBuffer [ 7 ] = service is null ? null : Expression . Constant ( service , serviceType ) ;
86
103
}
104
+
87
105
argsBuffer [ 0 ] = serviceName ;
88
106
argsBuffer [ 1 ] = on ;
89
107
argsBuffer [ 2 ] = m ;
@@ -93,7 +111,7 @@ bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t,
93
111
// 6, 7 set during array initialization
94
112
argsBuffer [ 8 ] = simplifiedExceptionHandling ;
95
113
96
- return ( bool ) s_addMethod . MakeGenericMethod ( typesBuffer ) . Invoke ( this , argsBuffer ) ! ;
114
+ return ( bool ) s_addMethod . MakeGenericMethod ( typesBuffer ) . Invoke ( this , argsBuffer ) ! ;
97
115
}
98
116
catch ( Exception fail )
99
117
{
@@ -106,7 +124,10 @@ bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t,
106
124
/// <summary>
107
125
/// Reports the number of operations available for a service
108
126
/// </summary>
109
- protected virtual void OnServiceBound ( object state , string serviceName , Type serviceType , Type serviceContract , int operationCount ) { }
127
+ protected virtual void OnServiceBound ( object state , string serviceName , Type serviceType , Type serviceContract ,
128
+ int operationCount )
129
+ {
130
+ }
110
131
111
132
private static readonly MethodInfo s_addMethod = typeof ( ServerBinder ) . GetMethod (
112
133
nameof ( AddMethod ) , BindingFlags . Instance | BindingFlags . NonPublic ) ! ;
@@ -133,7 +154,8 @@ protected readonly struct MethodStub<TService>
133
154
/// </summary>
134
155
public MethodInfo Method { get ; }
135
156
136
- internal MethodStub ( Func < MethodInfo , Expression [ ] , Expression > ? invoker , MethodInfo method , ConstantExpression ? service , bool simpleExceptionHandling )
157
+ internal MethodStub ( Func < MethodInfo , Expression [ ] , Expression > ? invoker , MethodInfo method ,
158
+ ConstantExpression ? service , bool simpleExceptionHandling )
137
159
{
138
160
_simpleExceptionHandling = simpleExceptionHandling ;
139
161
_invoker = invoker ;
@@ -163,7 +185,7 @@ public TDelegate CreateDelegate<TDelegate>()
163
185
else
164
186
{
165
187
// basic - direct call
166
- return ( TDelegate ) Delegate . CreateDelegate ( typeof ( TDelegate ) , _service , Method ) ;
188
+ return ( TDelegate ) Delegate . CreateDelegate ( typeof ( TDelegate ) , _service , Method ) ;
167
189
}
168
190
}
169
191
else
@@ -172,7 +194,8 @@ public TDelegate CreateDelegate<TDelegate>()
172
194
173
195
Expression [ ] mapArgs ;
174
196
if ( _service is null )
175
- { // if no service object, then the service is part of the signature, i.e. (svc, req) => svc.Blah();
197
+ {
198
+ // if no service object, then the service is part of the signature, i.e. (svc, req) => svc.Blah();
176
199
mapArgs = lambdaArgs ;
177
200
}
178
201
else
@@ -189,6 +212,7 @@ public TDelegate CreateDelegate<TDelegate>()
189
212
{
190
213
body = ApplySimpleExceptionHandling ( body ) ;
191
214
}
215
+
192
216
var lambda = Expression . Lambda < TDelegate > ( body , lambdaArgs ) ;
193
217
194
218
return lambda . Compile ( ) ;
@@ -204,17 +228,19 @@ static Expression ApplySimpleExceptionHandling(Expression body)
204
228
}
205
229
else if ( type . IsGenericType && type . GetGenericTypeDefinition ( ) == typeof ( Task < > ) )
206
230
{
207
- body = Expression . Call ( s_ReshapeWithSimpleExceptionHandling [ 1 ] . MakeGenericMethod ( type . GetGenericArguments ( ) ) , body ) ;
231
+ body = Expression . Call (
232
+ s_ReshapeWithSimpleExceptionHandling [ 1 ] . MakeGenericMethod ( type . GetGenericArguments ( ) ) , body ) ;
208
233
}
234
+
209
235
return body ;
210
236
}
211
237
}
212
238
213
239
#pragma warning disable CS0618
214
240
private static readonly Dictionary < int , MethodInfo > s_ReshapeWithSimpleExceptionHandling =
215
241
( from method in typeof ( Reshape ) . GetMethods ( BindingFlags . Public | BindingFlags . Static )
216
- where method . Name is nameof ( Reshape . WithSimpleExceptionHandling )
217
- select method )
242
+ where method . Name is nameof ( Reshape . WithSimpleExceptionHandling )
243
+ select method )
218
244
. ToDictionary ( method => method . IsGenericMethodDefinition ? method . GetGenericArguments ( ) . Length : 0 ) ;
219
245
#pragma warning restore CS0618
220
246
@@ -227,7 +253,8 @@ private bool AddMethod<TService, TRequest, TResponse>(
227
253
where TRequest : class
228
254
where TResponse : class
229
255
{
230
- var grpcMethod = new Method < TRequest , TResponse > ( methodType , serviceName , operationName , marshallerCache . GetMarshaller < TRequest > ( ) , marshallerCache . GetMarshaller < TResponse > ( ) ) ;
256
+ var grpcMethod = new Method < TRequest , TResponse > ( methodType , serviceName , operationName ,
257
+ marshallerCache . GetMarshaller < TRequest > ( ) , marshallerCache . GetMarshaller < TResponse > ( ) ) ;
231
258
var stub = new MethodStub < TService > ( invoker , method , service , simplfiedExceptionHandling ) ;
232
259
try
233
260
{
@@ -238,13 +265,13 @@ private bool AddMethod<TService, TRequest, TResponse>(
238
265
OnError ( ex . Message ) ;
239
266
return false ;
240
267
}
241
-
242
268
}
243
269
244
270
/// <summary>
245
271
/// The implementing binder should bind the method to the bind-state
246
272
/// </summary>
247
- protected abstract bool TryBind < TService , TRequest , TResponse > ( ServiceBindContext bindContext , Method < TRequest , TResponse > method , MethodStub < TService > stub )
273
+ protected abstract bool TryBind < TService , TRequest , TResponse > ( ServiceBindContext bindContext ,
274
+ Method < TRequest , TResponse > method , MethodStub < TService > stub )
248
275
where TService : class
249
276
where TRequest : class
250
277
where TResponse : class ;
@@ -255,12 +282,16 @@ protected abstract bool TryBind<TService, TRequest, TResponse>(ServiceBindContex
255
282
/// <summary>
256
283
/// Publish a warning message
257
284
/// </summary>
258
- protected internal virtual void OnWarn ( string message , object ? [ ] ? args = null ) { }
285
+ protected internal virtual void OnWarn ( string message , object ? [ ] ? args = null )
286
+ {
287
+ }
259
288
260
289
/// <summary>
261
290
/// Publish a warning message
262
291
/// </summary>
263
- protected internal virtual void OnError ( string message , object ? [ ] ? args = null ) { }
292
+ protected internal virtual void OnError ( string message , object ? [ ] ? args = null )
293
+ {
294
+ }
264
295
265
296
/// <summary>
266
297
/// Describes the relationship between a service contract and a service definition
@@ -304,4 +335,4 @@ public IList<object> GetMetadata(MethodInfo method)
304
335
=> ServiceBinder . GetMetadata ( method , ContractType , ServiceType ) ;
305
336
}
306
337
}
307
- }
338
+ }
0 commit comments