示例#1
0
        /// <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);
                }
            }
        }
示例#2
0
        /// <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);
                }
            }
        }