@@ -24,57 +24,77 @@ 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
- 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 }
43
44
: ContractOperation . ExpandInterfaces ( serviceType ) ;
44
45
45
46
bool serviceImplSimplifiedExceptions = serviceType . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) ) ;
46
- foreach ( var serviceContract in serviceContracts )
47
+ foreach ( var potentialServiceContract in potentialServiceContracts )
47
48
{
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).
49
60
50
- var serviceContractSimplifiedExceptions = serviceImplSimplifiedExceptions || serviceContract . IsDefined ( typeof ( SimpleRpcExceptionsAttribute ) ) ;
51
61
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 )
54
63
{
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 ) )
59
69
{
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
+ }
63
79
}
64
80
}
81
+
65
82
OnServiceBound ( state , serviceName ! , serviceType , serviceContract , svcOpCount ) ;
66
83
}
84
+
67
85
return totalCount ;
68
86
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 )
71
90
{
72
91
try
73
92
{
74
93
if ( typesBuffer . Length == 0 )
75
94
{
76
- typesBuffer = new Type [ ] { serviceType , typeof ( void ) , typeof ( void ) } ;
95
+ typesBuffer = new Type [ ] { serviceType , typeof ( void ) , typeof ( void ) } ;
77
96
}
97
+
78
98
typesBuffer [ 1 ] = @in ;
79
99
typesBuffer [ 2 ] = @out ;
80
100
@@ -84,6 +104,7 @@ bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t,
84
104
argsBuffer [ 6 ] = binderConfiguration ! . MarshallerCache ;
85
105
argsBuffer [ 7 ] = service is null ? null : Expression . Constant ( service , serviceType ) ;
86
106
}
107
+
87
108
argsBuffer [ 0 ] = serviceName ;
88
109
argsBuffer [ 1 ] = on ;
89
110
argsBuffer [ 2 ] = m ;
@@ -93,7 +114,7 @@ bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t,
93
114
// 6, 7 set during array initialization
94
115
argsBuffer [ 8 ] = simplifiedExceptionHandling ;
95
116
96
- return ( bool ) s_addMethod . MakeGenericMethod ( typesBuffer ) . Invoke ( this , argsBuffer ) ! ;
117
+ return ( bool ) s_addMethod . MakeGenericMethod ( typesBuffer ) . Invoke ( this , argsBuffer ) ! ;
97
118
}
98
119
catch ( Exception fail )
99
120
{
@@ -128,7 +149,8 @@ protected readonly struct MethodStub<TService>
128
149
/// </summary>
129
150
public MethodInfo Method { get ; }
130
151
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 )
132
154
{
133
155
_simpleExceptionHandling = simpleExceptionHandling ;
134
156
_invoker = invoker ;
@@ -158,7 +180,7 @@ public TDelegate CreateDelegate<TDelegate>()
158
180
else
159
181
{
160
182
// basic - direct call
161
- return ( TDelegate ) Delegate . CreateDelegate ( typeof ( TDelegate ) , _service , Method ) ;
183
+ return ( TDelegate ) Delegate . CreateDelegate ( typeof ( TDelegate ) , _service , Method ) ;
162
184
}
163
185
}
164
186
else
@@ -167,7 +189,8 @@ public TDelegate CreateDelegate<TDelegate>()
167
189
168
190
Expression [ ] mapArgs ;
169
191
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();
171
194
mapArgs = lambdaArgs ;
172
195
}
173
196
else
@@ -184,6 +207,7 @@ public TDelegate CreateDelegate<TDelegate>()
184
207
{
185
208
body = ApplySimpleExceptionHandling ( body ) ;
186
209
}
210
+
187
211
var lambda = Expression . Lambda < TDelegate > ( body , lambdaArgs ) ;
188
212
189
213
return lambda . Compile ( ) ;
@@ -199,17 +223,19 @@ static Expression ApplySimpleExceptionHandling(Expression body)
199
223
}
200
224
else if ( type . IsGenericType && type . GetGenericTypeDefinition ( ) == typeof ( Task < > ) )
201
225
{
202
- body = Expression . Call ( s_ReshapeWithSimpleExceptionHandling [ 1 ] . MakeGenericMethod ( type . GetGenericArguments ( ) ) , body ) ;
226
+ body = Expression . Call (
227
+ s_ReshapeWithSimpleExceptionHandling [ 1 ] . MakeGenericMethod ( type . GetGenericArguments ( ) ) , body ) ;
203
228
}
229
+
204
230
return body ;
205
231
}
206
232
}
207
233
208
234
#pragma warning disable CS0618
209
235
private static readonly Dictionary < int , MethodInfo > s_ReshapeWithSimpleExceptionHandling =
210
236
( 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 )
213
239
. ToDictionary ( method => method . IsGenericMethodDefinition ? method . GetGenericArguments ( ) . Length : 0 ) ;
214
240
#pragma warning restore CS0618
215
241
@@ -222,7 +248,8 @@ private bool AddMethod<TService, TRequest, TResponse>(
222
248
where TRequest : class
223
249
where TResponse : class
224
250
{
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 > ( ) ) ;
226
253
var stub = new MethodStub < TService > ( invoker , method , service , simplfiedExceptionHandling ) ;
227
254
try
228
255
{
@@ -235,13 +262,11 @@ private bool AddMethod<TService, TRequest, TResponse>(
235
262
OnError ( ex . Message ) ;
236
263
return false ;
237
264
}
238
-
239
265
}
240
266
241
267
void IBindContext . LogWarning ( string message , object ? [ ] ? args ) => OnWarn ( message , args ) ;
242
268
void IBindContext . LogError ( string message , object ? [ ] ? args ) => OnError ( message , args ) ;
243
269
244
- /// <summary>
245
270
/// Describes the relationship between a service contract and a service definition
246
271
/// </summary>
247
272
protected internal sealed class ServiceBindContext
@@ -283,4 +308,4 @@ public IList<object> GetMetadata(MethodInfo method)
283
308
=> ServiceBinder . GetMetadata ( method , ContractType , ServiceType ) ;
284
309
}
285
310
}
286
- }
311
+ }
0 commit comments