/// <summary>
        /// This method parses comments from C# XML documentation into the appropriate
        /// cHelpText properties.
        /// </summary>
        /// <returns></returns>
        public bool ParseXmlProperties(DotnetObject PassedObject)
        {
            string       xPath;
            DotnetObject Object;

            XmlDocument oDom = new XmlDocument();

            try
            {
                oDom.Load("file://" + cXmlFilename);
            }
            catch (Exception ex)
            {
                cErrorMsg = "Unable to load XML Documentation file." + ex.Message;
                return(false);
            }

            // *** Get object descriptions
            for (int Objs = 0; Objs < nObjectCount; Objs++)
            {
                XmlNode Match    = null;
                XmlNode SubMatch = null;

                if (PassedObject == null)
                {
                    Object = aObjects[Objs];
                }
                else
                {
                    Object = PassedObject;
                    Objs   = nObjectCount - 1;
                }

                if (PassedObject != null && PassedObject.Name.ToLower() != Object.Name.ToLower())
                {
                    continue;
                }

                try
                {
                    Match = oDom.SelectSingleNode("/doc/members/member[@name='" +
                                                  "T:" + Object.RawSignature + "']");

                    Object.HelpText = GetNodeValue(Match, "summary");

                    Object.Remarks = GetNodeValue(Match, "remarks");
                    Object.Example = GetExampleCode(Match);
                    Object.SeeAlso = FixupSeeAlsoLinks(ref Object.HelpText) +
                                     FixupSeeAlsoLinks(ref Object.Remarks);

                    Object.Contract = GetContracts(Match);

                    Match = null;
                }
                catch (Exception ex)
                {
                    string lcError = ex.Message;
                }

                // *** Loop through the methods
                for (int lnMethods = 0; lnMethods < Object.MethodCount; lnMethods++)
                {
                    ObjectMethod method = Object.Methods[lnMethods];

                    // *** Strip off empty method parens
                    string methodSignature = method.Signature.Replace("()", "");

                    // *** Replace Reference of Reflection for the one use by XML docs
                    methodSignature = methodSignature.Replace("&", "@");

                    if (method.RawParameters == "")
                    {
                        xPath = "/doc/members/member[@name='" +
                                "M:" + methodSignature + "']"; // .cNamespace + "." + loObject.cName + "." + loMethod.cName + "']";
                    }
                    else
                    {
                        xPath = "/doc/members/member[@name='" +
                                "M:" + methodSignature + "']";
                    }

                    //							"M:" + loObject.cNamespace + "." + loObject.cName + "." + loMethod.cName +
                    //							"(" + loMethod.cRawParameters + ")']";


                    try
                    {
                        Match = oDom.SelectSingleNode(xPath);
                        if (Match == null)
                        {
                            continue;
                        }

                        method.HelpText = GetNodeValue(Match, "summary");
                        method.Remarks  = GetNodeValue(Match, "remarks");
                        method.Example  = GetExampleCode(Match);
                        method.Contract = GetContracts(Match);

                        method.SeeAlso = FixupSeeAlsoLinks(ref method.HelpText) +
                                         FixupSeeAlsoLinks(ref method.Remarks);


                        //this.GetNodeValue(Match, "example");

                        // *** Only update returns if the return comment is actually set
                        // *** Otherwise leave the type intact
                        method.ReturnDescription = GetNodeValue(Match, "returns");

                        // *** Parse the parameters
                        string lcParmDescriptions = "";
                        for (int x = 0; x < method.ParameterCount; x++)
                        {
                            string parm = method.ParameterList[x].Trim();
                            lcParmDescriptions = lcParmDescriptions +
                                                 "**" + parm + "**  \r\n";

                            SubMatch = Match.SelectSingleNode("param[@name='" + parm + "']");
                            if (SubMatch != null)
                            {
                                string lcValue = SubMatch.InnerText;
                                if (lcValue.Length > 0)
                                {
                                    lcValue            = lcValue.Trim(' ', '\t', '\r', '\n');
                                    lcParmDescriptions = lcParmDescriptions + lcValue + "\r\n\r\n";
                                }
                                else
                                {
                                    // empty line
                                    lcParmDescriptions = lcParmDescriptions + "\r\n";
                                }
                            }
                        }
                        method.DescriptiveParameters = lcParmDescriptions;

                        string      Exceptions       = "";
                        XmlNodeList ExceptionMatches = null;
                        try
                        {
                            ExceptionMatches = Match.SelectNodes("exception");
                        }
                        catch {; }

                        if (ExceptionMatches != null)
                        {
                            foreach (XmlNode Node in ExceptionMatches)
                            {
                                XmlAttribute Ref = Node.Attributes["cref"];
                                if (Ref != null)
                                {
                                    Exceptions += "**" + Ref.Value.Replace("T:", "").Replace("!:", "") + "**  \r\n";
                                }
                                if (!string.IsNullOrEmpty(Node.InnerText))
                                {
                                    Exceptions += GetNodeValue(Node, "") + "\r\n";
                                }
                                Exceptions += "\r\n";
                            }
                            method.Exceptions = Exceptions.TrimEnd('\r', '\n');
                        }

                        Match = null;
                    }
                    catch (Exception ex)
                    {
                        string lcError = ex.Message;
                    }
                }  // for methods

                // *** Loop through the properties
                for (int lnFields = 0; lnFields < Object.PropertyCount; lnFields++)
                {
                    ObjectProperty property = Object.Properties[lnFields];

                    string fieldPrefix = "F:";
                    if (property.FieldOrProperty != "Field")
                    {
                        fieldPrefix = "P:";
                    }

                    xPath = "/doc/members/member[@name='" + fieldPrefix +
                            property.Signature + "']";

                    Match = oDom.SelectSingleNode(xPath);

                    property.HelpText = GetNodeValue(Match, "summary");
                    property.Remarks  = GetNodeValue(Match, "remarks");
                    property.Example  = GetExampleCode(Match);
                    property.Contract = GetContracts(Match);

                    property.SeeAlso = FixupSeeAlsoLinks(ref property.HelpText) +
                                       FixupSeeAlsoLinks(ref property.Remarks);


                    string value = GetNodeValue(Match, "value");
                    if (!string.IsNullOrEmpty(value))
                    {
                        property.DefaultValue = value;
                    }

                    Match = null;
                }  // for properties

                // *** Loop through the fields
                for (int lnFields = 0; lnFields < Object.EventCount; lnFields++)
                {
                    ObjectEvent loEvent = Object.Events[lnFields];

                    string lcFieldPrefix = "E:";

                    xPath = "/doc/members/member[@name='" + lcFieldPrefix +
                            loEvent.Signature + "']";

                    Match            = oDom.SelectSingleNode(xPath);
                    loEvent.HelpText = GetNodeValue(Match, "summary");
                    loEvent.Remarks  = GetNodeValue(Match, "remarks");
                    loEvent.Example  = GetExampleCode(Match);

                    loEvent.SeeAlso = FixupSeeAlsoLinks(ref loEvent.HelpText) +
                                      FixupSeeAlsoLinks(ref loEvent.Remarks);

                    Match = null;
                } // for events
            }     // for objects

            return(true);
        } // ParseXMLProperties (method)
        private void ParseMethodsOnType(DotnetObject dotnetObject, Collection <MethodDefinition> methods, TypeDefinition dotnetType)
        {
            var methodList = new List <ObjectMethod>();

            foreach (var mi in methods)
            {
                var meth  = new ObjectMethod();
                var miRef = mi.GetElementMethod();

                if (NoInheritedMembers && miRef.DeclaringType != dotnetType)
                {
                    continue;
                }

                meth.Name = mi.Name;
                if (meth.Name.StartsWith("<") || mi.IsGetter || mi.IsSetter || mi.IsAddOn || mi.IsRemoveOn || mi.IsPrivate)
                {
                    continue;
                }


                meth.Classname = mi.DeclaringType.Name;

                if (mi.IsConstructor)
                {
                    // no static or base class constructors
                    if (mi.IsStatic || mi.DeclaringType.FullName != dotnetObject.TypeDefinition.FullName)
                    {
                        continue; // don't document static constructors
                    }
                    meth.IsConstructor = true;
                    meth.Name          = dotnetObject.Name;
                }

                if (mi.IsPublic)
                {
                    meth.Scope = "public";
                }
                // TODO: Internal Protected needs to be addressed
                else if (mi.IsAssembly || mi.IsFamilyOrAssembly)
                {
                    meth.Scope    = "internal";
                    meth.Internal = true;
                }
                else if (mi.IsPrivate)
                {
                    meth.Scope = "private";
                }

                if (mi.IsAbstract)
                {
                    meth.Other += "abstract ";
                }

                if (mi.IsVirtual && !mi.IsAbstract)
                {
                    meth.Other += "virtual ";
                }

                if (mi.IsStatic)
                {
                    meth.Static = mi.IsStatic;
                    meth.Other += "static ";
                }

                if (mi.IsFinal)
                {
                    meth.Other += "sealed ";
                }

                if (mi.HasGenericParameters || mi.ContainsGenericParameter)
                {
                    meth.GenericParameters = "<";
                    var genericParms = miRef.GenericParameters;
                    foreach (var genericArg in genericParms)
                    {
                        meth.GenericParameters += genericArg.Name + ",";
                    }

                    meth.GenericParameters  = meth.GenericParameters.TrimEnd(',');
                    meth.GenericParameters += ">";
                    if (meth.GenericParameters == "<>")
                    {
                        meth.GenericParameters = "";
                    }
                }

                foreach (var parm in mi.Parameters)
                {
                    var methodParm = new MethodParameter();
                    methodParm.Name = parm.Name;
                    if (methodParm.Name.EndsWith("&"))
                    {
                        methodParm.Other = "ref ";
                        methodParm.Name  = methodParm.Name.TrimEnd('&');
                    }

                    methodParm.ShortTypeName = FixupStringTypeName(parm.ParameterType.Name);
                    if (parm.ParameterType.IsGenericInstance)
                    {
                        methodParm.ShortTypeName =
                            DotnetObject.GetGenericTypeName(parm.ParameterType.GetElementType(),
                                                            GenericTypeNameFormats.TypeName);
                    }


                    methodParm.Type = parm.ParameterType.FullName;


                    meth.ParameterList.Add(methodParm);
                }

                meth.ReturnType = mi.ReturnType.FullName;

                var simpleRetName = mi.ReturnType.Name;
                if (!mi.ReturnType.IsGenericParameter)
                {
                    simpleRetName = FixupStringTypeName(simpleRetName);
                }

                var sbSyntax = new StringBuilder();
                sbSyntax.Append($"{dotnetObject.Scope} {dotnetObject.Other} {simpleRetName} {meth.Name}{meth.GenericParameters}(");

                var parmCounter = 0;
                foreach (var parm in meth.ParameterList)
                {
                    sbSyntax.Append($"{parm.ShortTypeName} {parm.Name}, ");
                    parmCounter++;
                    if (parmCounter % 2 == 0)
                    {
                        sbSyntax.Append("\r\n\t\t\t");
                    }
                }

                meth.Syntax = sbSyntax.ToString();
                meth.Syntax = meth.Syntax.TrimEnd(' ', ',', '\r', '\n', '\t') + ")";
                meth.Syntax = meth.Syntax.Replace("   ", " ").Replace("  ", " ");

                if (meth.IsConstructor)
                {
                    meth.Signature = mi.DeclaringType.FullName + ".#ctor";
                }

                string parameters    = "";
                string rawParameters = "";


                meth.Signature = mi.FullName;

                // strip off return type
                var idx = meth.Signature.IndexOf(' ');
                if (idx > -1)
                {
                    meth.Signature = meth.Signature.Substring(idx).TrimStart();
                }

                // fix up ctor
                meth.Signature = meth.Signature.Replace("::.ctor", ".#ctor");

                // fix up object member syntax and double conversions
                meth.Signature = meth.Signature
                                 .Replace("::", ".")
                                 .Replace("..", ".")
                                 .Trim();

                // fix up parameters
                if (meth.Signature.EndsWith("()"))
                {
                    // no parms has no parens ie. .method
                    meth.Signature = meth.Signature.Substring(0, meth.Signature.Length - 2);
                }
                else
                {
                    // fix up parameters for generics
                    // from:  .method(System.Collections.Generic.IDictionary`2(System.String,System.Object),System.String)
                    // to:    .method(System.Collections.Generic.IDictionary{System.String,System.Object},System.String)
                    var origParms = StringUtils.ExtractString(meth.Signature, "(", ")", returnDelimiters: true);
                    var newParms  = origParms;
                    if (origParms.Contains("`"))
                    {
                        var regEx   = new Regex("`.*?<(.*?)>");
                        var matches = regEx.Matches(meth.Signature);
                        foreach (Match match in matches)
                        {
                            var orig = match.Value;
                            var type = match.Groups[1].Value;
                            newParms = newParms.Replace(orig, "{" + type + "}");
                        }
                    }

                    if (!newParms.Equals(origParms))
                    {
                        meth.Signature = meth.Signature.Replace(origParms, newParms);
                    }
                }

                methodList.Add(meth);
            }

            dotnetObject.AllMethods.AddRange(methodList
                                             .OrderBy(ml => !ml.IsConstructor)
                                             .ThenBy(ml => ml.Name.ToLowerInvariant()));
        }