/// <summary> /// Initiate a bind operation, causing all service methods to be crawled for the provided type /// </summary> public int Bind(object state, Type serviceType, BinderConfiguration?binderConfiguration = null, object?service = null) { int totalCount = 0; object?[]? argsBuffer = null; Type[] typesBuffer = Array.Empty <Type>(); string? serviceName; if (binderConfiguration == null) { binderConfiguration = BinderConfiguration.Default; } var serviceContracts = typeof(IGrpcService).IsAssignableFrom(serviceType) ? new HashSet <Type> { serviceType } : ContractOperation.ExpandInterfaces(serviceType); var immediateServices = serviceContracts .Except(serviceContracts.SelectMany(t => t.GetInterfaces())) .Where(t => binderConfiguration.Binder.IsServiceContract(t, out _)); foreach (var serviceContract in serviceContracts) { // If not service then try to use TService for serviceName if (!binderConfiguration.Binder.IsServiceContract(serviceContract, out serviceName)) { var parentService = immediateServices.FirstOrDefault(s => serviceContract.IsAssignableFrom(s)); if (parentService is null) { continue; } else { binderConfiguration.Binder.IsServiceContract(parentService, out serviceName); } } int svcOpCount = 0; foreach (var op in ContractOperation.FindOperations(binderConfiguration, serviceContract)) { if (ServerInvokerLookup.TryGetValue(op.MethodType, op.Context, op.Result, op.Void, out var invoker) && AddMethod(op.From, op.To, op.Name, op.Method, op.MethodType, invoker)) { // yay! totalCount++; svcOpCount++; } } OnServiceBound(state, serviceName !, serviceType, serviceContract, svcOpCount); } return(totalCount); bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t, Func <MethodInfo, ParameterExpression[], Expression>?invoker) { try { if (typesBuffer.Length == 0) { typesBuffer = new Type[] { serviceType, typeof(void), typeof(void) }; } typesBuffer[1] = @in; typesBuffer[2] = @out; if (argsBuffer == null) { argsBuffer = new object?[] { null, null, null, null, state, null, binderConfiguration !.MarshallerCache, service == null ? null : Expression.Constant(service, serviceType) }; } argsBuffer[0] = serviceName; argsBuffer[1] = on; argsBuffer[2] = m; argsBuffer[3] = t; argsBuffer[5] = invoker; return((bool)s_addMethod.MakeGenericMethod(typesBuffer).Invoke(this, argsBuffer) !); } catch (Exception fail) { if (fail is TargetInvocationException tie) { fail = tie.InnerException !; } return(false); } } }
/// <summary> /// Initiate a bind operation, causing all service methods to be crawled for the provided type /// </summary> public int Bind(object state, Type serviceType, BinderConfiguration?binderConfiguration = null, object?service = null) { if (binderConfiguration == null) { binderConfiguration = BinderConfiguration.Default; } int totalCount = 0; object?[]? argsBuffer = null; Type[] typesBuffer = Array.Empty <Type>(); string? serviceName; if (binderConfiguration == null) { binderConfiguration = BinderConfiguration.Default; } foreach (var serviceContract in ContractOperation.ExpandInterfaces(serviceType)) { if (!binderConfiguration.Binder.IsServiceContract(serviceContract, out serviceName)) { continue; } int svcOpCount = 0; foreach (var op in ContractOperation.FindOperations(binderConfiguration, serviceContract)) { if (ServerInvokerLookup.TryGetValue(op.MethodType, op.Context, op.Result, op.Void, out var invoker) && AddMethod(op.From, op.To, op.Name, op.Method, op.MethodType, invoker)) { // yay! totalCount++; svcOpCount++; } } OnServiceBound(state, serviceName, serviceType, serviceContract, svcOpCount); } return(totalCount); bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t, Func <MethodInfo, ParameterExpression[], Expression>?invoker) { try { if (typesBuffer.Length == 0) { typesBuffer = new Type[] { serviceType, typeof(void), typeof(void) }; } typesBuffer[1] = @in; typesBuffer[2] = @out; if (argsBuffer == null) { argsBuffer = new object?[] { null, null, null, null, state, null, binderConfiguration !.MarshallerCache, service == null ? null : Expression.Constant(service, serviceType) }; } argsBuffer[0] = serviceName; argsBuffer[1] = on; argsBuffer[2] = m; argsBuffer[3] = t; argsBuffer[5] = invoker; return((bool)s_addMethod.MakeGenericMethod(typesBuffer).Invoke(this, argsBuffer) !); } catch (Exception fail) { if (fail is TargetInvocationException tie) { fail = tie.InnerException !; } return(false); } } }
/// <summary> /// Initiate a bind operation, causing all service methods to be crawled for the provided type /// </summary> public int Bind(object state, Type serviceType, BinderConfiguration?binderConfiguration = null, object?service = null) { int totalCount = 0; object?[]? argsBuffer = null; Type[] typesBuffer = Array.Empty <Type>(); string? serviceName; if (binderConfiguration == null) { binderConfiguration = BinderConfiguration.Default; } var serviceContracts = typeof(IGrpcService).IsAssignableFrom(serviceType) ? new HashSet <Type> { serviceType } : ContractOperation.ExpandInterfaces(serviceType); bool serviceImplSimplifiedExceptions = serviceType.IsDefined(typeof(SimpleRpcExceptionsAttribute)); foreach (var serviceContract in serviceContracts) { if (!binderConfiguration.Binder.IsServiceContract(serviceContract, out serviceName)) { continue; } var serviceContractSimplifiedExceptions = serviceImplSimplifiedExceptions || serviceContract.IsDefined(typeof(SimpleRpcExceptionsAttribute)); int svcOpCount = 0; var bindCtx = new ServiceBindContext(serviceContract, serviceType, state, binderConfiguration.Binder); foreach (var op in ContractOperation.FindOperations(binderConfiguration, serviceContract, this)) { if (ServerInvokerLookup.TryGetValue(op.MethodType, op.Context, op.Result, op.Void, out var invoker) && AddMethod(op.From, op.To, op.Name, op.Method, op.MethodType, invoker, bindCtx, serviceContractSimplifiedExceptions || op.Method.IsDefined(typeof(SimpleRpcExceptionsAttribute)) )) { // yay! totalCount++; svcOpCount++; } } OnServiceBound(state, serviceName !, serviceType, serviceContract, svcOpCount); } return(totalCount); bool AddMethod(Type @in, Type @out, string on, MethodInfo m, MethodType t, Func <MethodInfo, ParameterExpression[], Expression>?invoker, ServiceBindContext bindContext, bool simplifiedExceptionHandling) { try { if (typesBuffer.Length == 0) { typesBuffer = new Type[] { serviceType, typeof(void), typeof(void) }; } typesBuffer[1] = @in; typesBuffer[2] = @out; if (argsBuffer is null) { argsBuffer = new object?[9]; argsBuffer[6] = binderConfiguration !.MarshallerCache; argsBuffer[7] = service is null ? null : Expression.Constant(service, serviceType); } argsBuffer[0] = serviceName; argsBuffer[1] = on; argsBuffer[2] = m; argsBuffer[3] = t; argsBuffer[4] = bindContext; argsBuffer[5] = invoker; // 6, 7 set during array initialization argsBuffer[8] = simplifiedExceptionHandling; return((bool)s_addMethod.MakeGenericMethod(typesBuffer).Invoke(this, argsBuffer) !); } catch (Exception fail) { if (fail is TargetInvocationException tie) { fail = tie.InnerException !; } return(false); } } }