static void WriteMethod(
            HtmlTextWriter wrtr,
            XmlRpcMethodInfo mthdInfo,
            ArrayList structs)
        {
            wrtr.WriteFullBeginTag("span");
              wrtr.WriteLine();
              wrtr.WriteFullBeginTag("h2");
              wrtr.WriteBeginTag("a");
              wrtr.WriteAttribute("name", "#"+mthdInfo.XmlRpcName);
              wrtr.Write(HtmlTextWriter.TagRightChar);
              wrtr.Write("method " + mthdInfo.XmlRpcName);
              wrtr.WriteEndTag("a");
              wrtr.WriteEndTag("h2");
              wrtr.WriteLine();

              if (mthdInfo.Doc != "")
              {
            wrtr.WriteBeginTag("p");
            wrtr.WriteAttribute("class", "intro");
            wrtr.Write(HtmlTextWriter.TagRightChar);
            wrtr.Write(mthdInfo.Doc);
            wrtr.WriteEndTag("p");
            wrtr.WriteLine();
              }

              wrtr.WriteFullBeginTag("h3");
              wrtr.Write("Parameters");
              wrtr.WriteEndTag("h3");
              wrtr.WriteLine();

              wrtr.WriteBeginTag("table");
              wrtr.WriteAttribute("cellspacing", "0");
              wrtr.WriteAttribute("cellpadding", "5");
              wrtr.WriteAttribute("width", "90%");
              wrtr.Write(HtmlTextWriter.TagRightChar);

              if (mthdInfo.Parameters.Length > 0)
              {
            foreach (XmlRpcParameterInfo parInfo in mthdInfo.Parameters)
            {
              wrtr.WriteFullBeginTag("tr");
              wrtr.WriteBeginTag("td");
              wrtr.WriteAttribute("width", "33%");
              wrtr.Write(HtmlTextWriter.TagRightChar);
              WriteType(wrtr, parInfo.Type, parInfo.IsParams, structs);
              wrtr.WriteEndTag("td");

              wrtr.WriteFullBeginTag("td");
              if (parInfo.Doc == "")
            wrtr.Write(parInfo.Name);
              else
              {
            wrtr.Write(parInfo.Name);
            wrtr.Write(" - ");
            wrtr.Write(parInfo.Doc);
              }
              wrtr.WriteEndTag("td");
              wrtr.WriteEndTag("tr");
            }
              }
              else
              {
            wrtr.WriteFullBeginTag("tr");
            wrtr.WriteBeginTag("td");
            wrtr.WriteAttribute("width", "33%");
            wrtr.Write(HtmlTextWriter.TagRightChar);
            wrtr.Write("none");
            wrtr.WriteEndTag("td");
            wrtr.WriteFullBeginTag("td");
            wrtr.Write(" ");
            wrtr.WriteEndTag("td");
            wrtr.WriteEndTag("tr");
              }
              wrtr.WriteEndTag("table");
              wrtr.WriteLine();
              wrtr.WriteFullBeginTag("h3");
              wrtr.Write("Return Value");
              wrtr.WriteEndTag("h3");
              wrtr.WriteLine();

              wrtr.WriteBeginTag("table");
              wrtr.WriteAttribute("cellspacing", "0");
              wrtr.WriteAttribute("cellpadding", "5");
              wrtr.WriteAttribute("width", "90%");
              wrtr.Write(HtmlTextWriter.TagRightChar);

              wrtr.WriteFullBeginTag("tr");

              wrtr.WriteBeginTag("td");
              wrtr.WriteAttribute("width", "33%");
              wrtr.Write(HtmlTextWriter.TagRightChar);
              WriteType(wrtr, mthdInfo.ReturnType, false, structs);
              wrtr.WriteEndTag("td");

              wrtr.WriteFullBeginTag("td");
              if (mthdInfo.ReturnDoc != "")
            wrtr.Write(mthdInfo.ReturnDoc);
              else
            wrtr.Write(" ");
              wrtr.WriteEndTag("td");

              wrtr.WriteEndTag("tr");

              wrtr.WriteEndTag("table");
              wrtr.WriteLine();

              wrtr.WriteEndTag("span");
              wrtr.WriteLine();
        }
        static void ExtractMethodInfo(Hashtable methods, MethodInfo mi, Type type)
        {
            XmlRpcMethodAttribute attr = (XmlRpcMethodAttribute)
            Attribute.GetCustomAttribute(mi,
            typeof(XmlRpcMethodAttribute));
              if (attr == null)
            return;
              XmlRpcMethodInfo mthdInfo = new XmlRpcMethodInfo();
              mthdInfo.MethodInfo = mi;
              mthdInfo.XmlRpcName = GetXmlRpcMethodName(mi);
              mthdInfo.MiName = mi.Name;
              mthdInfo.Doc = attr.Description;
              mthdInfo.IsHidden = attr.IntrospectionMethod | attr.Hidden;
              // extract parameters information
              ArrayList parmList = new ArrayList();
              ParameterInfo[] parms = mi.GetParameters();
              foreach (ParameterInfo parm in parms)
              {
            XmlRpcParameterInfo parmInfo = new XmlRpcParameterInfo();
            parmInfo.Name = parm.Name;
            parmInfo.Type = parm.ParameterType;
            parmInfo.XmlRpcType = GetXmlRpcTypeString(parm.ParameterType);
            // retrieve optional attributed info
            parmInfo.Doc = "";
            XmlRpcParameterAttribute pattr = (XmlRpcParameterAttribute)
              Attribute.GetCustomAttribute(parm,
              typeof(XmlRpcParameterAttribute));
            if (pattr != null)
            {
              parmInfo.Doc = pattr.Description;
              parmInfo.XmlRpcName = pattr.Name;
            }
            parmInfo.IsParams = Attribute.IsDefined(parm,
              typeof(ParamArrayAttribute));
            parmList.Add(parmInfo);
              }
              mthdInfo.Parameters = (XmlRpcParameterInfo[])
            parmList.ToArray(typeof(XmlRpcParameterInfo));
              // extract return type information
              mthdInfo.ReturnType = mi.ReturnType;
              mthdInfo.ReturnXmlRpcType = GetXmlRpcTypeString(mi.ReturnType);
              object[] orattrs = mi.ReturnTypeCustomAttributes.GetCustomAttributes(
            typeof(XmlRpcReturnValueAttribute), false);
              if (orattrs.Length > 0)
              {
            mthdInfo.ReturnDoc = ((XmlRpcReturnValueAttribute)orattrs[0]).Description;
              }

              if (methods[mthdInfo.XmlRpcName] != null)
              {
            throw new XmlRpcDupXmlRpcMethodNames(String.Format("Method "
              + "{0} in type {1} has duplicate XmlRpc method name {2}",
              mi.Name, type.Name, mthdInfo.XmlRpcName));
              }
              else
            methods.Add(mthdInfo.XmlRpcName, mthdInfo);
        }