protected override bool TryBind <TService, TRequest, TResponse>(ServiceBindContext bindContext, Method <TRequest, TResponse> method, MethodStub <TService> stub)
                where TService : class
                where TRequest : class
                where TResponse : class
            {
                var builder = (ServerServiceDefinition.Builder)bindContext.State;

                switch (method.Type)
                {
                case MethodType.Unary:
                    builder.AddMethod(method, stub.CreateDelegate <UnaryServerMethod <TRequest, TResponse> >());
                    break;

                case MethodType.ClientStreaming:
                    builder.AddMethod(method, stub.CreateDelegate <ClientStreamingServerMethod <TRequest, TResponse> >());
                    break;

                case MethodType.ServerStreaming:
                    builder.AddMethod(method, stub.CreateDelegate <ServerStreamingServerMethod <TRequest, TResponse> >());
                    break;

                case MethodType.DuplexStreaming:
                    builder.AddMethod(method, stub.CreateDelegate <DuplexStreamingServerMethod <TRequest, TResponse> >());
                    break;

                default:
                    return(false);
                }
                _log?.WriteLine($"{method.ServiceName} / {method.Name} ({method.Type}) bound to {stub.Method.DeclaringType.Name}.{stub.Method.Name}");
                return(true);
            }
            protected override bool TryBind <TService, TRequest, TResponse>(ServiceBindContext bindContext, Method <TRequest, TResponse> method, MethodStub <TService> stub)
                where TService : class
                where TRequest : class
                where TResponse : class
            {
                var metadata = bindContext.GetMetadata(stub.Method);

                var context = (ServiceMethodProviderContext <TService>)bindContext.State;

                switch (method.Type)
                {
                case MethodType.Unary:
                    context.AddUnaryMethod(method, metadata, stub.CreateDelegate <UnaryServerMethod <TService, TRequest, TResponse> >());
                    break;

                case MethodType.ClientStreaming:
                    context.AddClientStreamingMethod(method, metadata, stub.CreateDelegate <ClientStreamingServerMethod <TService, TRequest, TResponse> >());
                    break;

                case MethodType.ServerStreaming:
                    context.AddServerStreamingMethod(method, metadata, stub.CreateDelegate <ServerStreamingServerMethod <TService, TRequest, TResponse> >());
                    break;

                case MethodType.DuplexStreaming:
                    context.AddDuplexStreamingMethod(method, metadata, stub.CreateDelegate <DuplexStreamingServerMethod <TService, TRequest, TResponse> >());
                    break;

                default:
                    return(false);
                }
                return(true);
            }
            protected override bool TryBind <TService, TRequest, TResponse>(object state, Method <TRequest, TResponse> method, MethodStub <TService> stub)
                where TService : class
                where TRequest : class
                where TResponse : class
            {
                var metadata = new List <object>();

                // Add type metadata first so it has a lower priority
                metadata.AddRange(typeof(TService).GetCustomAttributes(inherit: true));
                // Add method metadata last so it has a higher priority
                metadata.AddRange(stub.Method.GetCustomAttributes(inherit: true));

                var implementedMethod = typeof(TService).GetMethod(stub.Method.Name, stub.Method.GetParameters()
                                                                   .Select(s => s.ParameterType)
                                                                   .ToArray());

                if (implementedMethod != null)
                {
                    metadata.AddRange(implementedMethod.GetCustomAttributes(inherit: true));
                }

                var context = (ServiceMethodProviderContext <TService>)state;

                switch (method.Type)
                {
                case MethodType.Unary:
                    context.AddUnaryMethod(method, metadata, stub.CreateDelegate <UnaryServerMethod <TService, TRequest, TResponse> >());
                    break;

                case MethodType.ClientStreaming:
                    context.AddClientStreamingMethod(method, metadata, stub.CreateDelegate <ClientStreamingServerMethod <TService, TRequest, TResponse> >());
                    break;

                case MethodType.ServerStreaming:
                    context.AddServerStreamingMethod(method, metadata, stub.CreateDelegate <ServerStreamingServerMethod <TService, TRequest, TResponse> >());
                    break;

                case MethodType.DuplexStreaming:
                    context.AddDuplexStreamingMethod(method, metadata, stub.CreateDelegate <DuplexStreamingServerMethod <TService, TRequest, TResponse> >());
                    break;

                default:
                    return(false);
                }
                return(true);
            }