private void AddMethod(Control parent, IRpcMethodDescriptor method)
        {
            JsonRpcObsoleteAttribute obsoleteAttribute = JsonRpcObsoleteAttribute.Get(method.AttributeProvider);

            Control methodSpan = AddSpan(parent, 
                obsoleteAttribute == null ? "method" : "method obsolete-method", null);
    
            HyperLink link = new HyperLink();
            link.CssClass = "method-name";
            link.Text = Server.HtmlEncode(method.Name);
            methodSpan.Controls.Add(link);

            AddSignature(methodSpan, method);
            string summary = JsonRpcHelpAttribute.GetText(method.AttributeProvider);

            if (summary.Length > 0)
            {
                AddSpan(parent, "method-summary-sep", " - ");
                AddSpan(parent, "method-summary", summary);
            }

            if (obsoleteAttribute != null)
            {
                AddSpan(parent, "obsolete-message", " This method has been obsoleted. " + obsoleteAttribute.Message);
            }
        }
        /// <summary>
        /// Takes an array of arguments that are designated for a method and
        /// transposes them if the target method supports variable arguments (in
        /// other words, the last parameter is annotated with the JsonRpcParams
        /// attribute). If the method does not support variable arguments then
        /// the input array is returned verbatim. 
        /// </summary>

        // TODO: Allow args to be null to represent empty arguments.
        // TODO: Allow parameter conversions

        public static object[] TransposeVariableArguments(IRpcMethodDescriptor method, object[] args)
        {
            if (method == null)
                throw new ArgumentNullException("method");

            //
            // If the method does not have take variable arguments then just
            // return the arguments array verbatim.
            //

            if (!HasMethodVariableArguments(method))
                return args;

            int parameterCount = method.GetParameters().Length;

            object[] varArgs = null;
            
            if (args.Length >= parameterCount)
            {
                object lastArg = args[args.Length - 1];

                if (lastArg != null)
                {
                    varArgs = lastArg as object[];
                
                    if (varArgs == null)
                    {
                        ICollection collection = lastArg as ICollection;    
                    
                        if (collection != null)
                        {
                            varArgs = new object[collection.Count];
                            collection.CopyTo(varArgs, 0);
                        }
                    }
                }
            }

            //
            // Copy out the extra arguments into a new array that represents
            // the variable parts.
            //

            if (varArgs == null)
            {
                varArgs = new object[(args.Length - parameterCount) + 1];
                Array.Copy(args, parameterCount - 1, varArgs, 0, varArgs.Length);
            }

            //
            // Setup a new array of arguments that has a copy of the fixed
            // arguments followed by the variable arguments array setup above.
            //

            object[] transposedArgs = new object[parameterCount];
            Array.Copy(args, transposedArgs, parameterCount - 1);
            transposedArgs[transposedArgs.Length - 1] = varArgs;
            return transposedArgs;
        }
        public RpcParameterDescriptor(IRpcMethodDescriptor method, ParameterInfo parameter)
        {
            if (method == null)
                throw new ArgumentNullException("method");

            if (parameter == null)
                throw new ArgumentNullException("parameter");

            _method = method;
            _parameter = parameter;

            // TODO: Parameter validation, e.g. cannot be by-reference.
        }
        private void AddMethod(Control parent, IRpcMethodDescriptor method)
        {
            JsonRpcObsoleteAttribute obsoleteAttribute = JsonRpcObsoleteAttribute.Get(method.AttributeProvider);

            Control methodTerm = AddGeneric(parent, "dt", obsoleteAttribute == null ? "method" : "method obsolete-method");
            AddSpan(methodTerm, "method-name", method.Name);
            AddSignature(methodTerm, method);

            string summary = JsonRpcHelpAttribute.GetText(method.AttributeProvider);

            if (summary.Length > 0 || obsoleteAttribute != null)
            {
                AddGeneric(parent, "dd", "method-summary", summary);

                if (obsoleteAttribute != null)
                    AddSpan(parent, "obsolete-message", " This method has been obsoleted. " + obsoleteAttribute.Message);
            }
        }
        private static void AddSignature(Control parent, IRpcMethodDescriptor method)
        {
            Control methodSignatureSpan = AddSpan(parent, "method-sig", null);
            AddSpan(methodSignatureSpan, "method-param-open", "(");
    
            IRpcParameterDescriptor[] parameters = method.GetParameters();
            foreach (IRpcParameterDescriptor parameter in parameters)
            {
                if (parameter.Position > 0)
                    AddSpan(methodSignatureSpan, "method-param-delim", ", ");

                AddSpan(methodSignatureSpan, "method-param", parameter.Name);
            }
    
            AddSpan(methodSignatureSpan, "method-param-close", ")");
        }
        /// <summary>
        /// Determines if the method accepts variable number of arguments or
        /// not. A method is designated as accepting variable arguments by
        /// annotating the last parameter of the method with the JsonRpcParams
        /// attribute.
        /// </summary>

        public static bool HasMethodVariableArguments(IRpcMethodDescriptor method)
        {
            if (method == null)
                throw new ArgumentNullException("method");

            IRpcParameterDescriptor[] parameters = method.GetParameters();
            int parameterCount = parameters.Length;

            if (parameterCount == 0)
                return false;

            IRpcParameterDescriptor lastParameter = parameters[parameterCount - 1];
            return JsonRpcParamsAttribute.IsDefined(lastParameter.AttributeProvider);
        }
        public static object[] MapArguments(IRpcMethodDescriptor method, object argsObject)
        {
            object[] args;
            IDictionary argsMap = argsObject as IDictionary;

            if (argsMap != null)
            {
                JObject namedArgs = new JObject(argsMap);
                
                IRpcParameterDescriptor[] parameters = method.GetParameters();
                args = new object[parameters.Length];

                for (int i = 0; i < parameters.Length; i++)
                {
                    args[i] = namedArgs[parameters[i].Name];
                    namedArgs.Remove(parameters[i].Name);
                }

                foreach (DictionaryEntry entry in namedArgs)
                {
                    if (entry.Key == null)
                        continue;

                    string key = entry.Key.ToString();
                    
                    char ch1;
                    char ch2;

                    if (key.Length == 2)
                    {
                        ch1 = key[0];
                        ch2 = key[1];
                    }
                    else if (key.Length == 1)
                    {
                        ch1 = '0';
                        ch2 = key[0];
                    }
                    else
                    {
                        continue;
                    }

                    if (ch1 >= '0' && ch1 < '9' &&
                        ch2 >= '0' && ch2 < '9')
                    {
                        int index = int.Parse(key, NumberStyles.Number, CultureInfo.InvariantCulture);
                        
                        if (index < parameters.Length)
                            args[index] = entry.Value;
                    }
                }

                return args;
            }
            else
            {
                args = CollectionHelper.ToArray((ICollection) argsObject);
            }

            return JsonRpcServices.TransposeVariableArguments(method, args);
        }
 protected object Invoke(IRpcMethodDescriptor method, object[] args)
 {    
     return ((RpcMethodDescriptor) method).Invoke(this, args);
 }