private CodeDocMethod ConvertToModel(MethodBase methodBase, CodeDocMemberDetailLevel detailLevel, ICodeDocMemberDataProvider extraMemberDataProvider = null)
            {
                Contract.Requires(methodBase != null);
                Contract.Ensures(Contract.Result<CodeDocMethod>() != null);
                Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<CodeDocMethod>().ShortName));
                Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<CodeDocMethod>().FullName));
                Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<CodeDocMethod>().Title));
                Contract.Ensures(Contract.Result<CodeDocMethod>().Title == Contract.Result<CodeDocMethod>().ShortName);
                Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<CodeDocMethod>().SubTitle));

                var includeExceptions = detailLevel != CodeDocMemberDetailLevel.Minimum;
                var appendXmlDoc = detailLevel.HasFlag(CodeDocMemberDetailLevel.Summary) || detailLevel.HasFlag(CodeDocMemberDetailLevel.AdditionalContents);
                var provideXmlDoc = includeExceptions || detailLevel != CodeDocMemberDetailLevel.Minimum;
                var includeInheritance = detailLevel.HasFlag(CodeDocMemberDetailLevel.Inheritance);
                var includeParameters = detailLevel != CodeDocMemberDetailLevel.Minimum;

                var methodInfo = methodBase as MethodInfo;
                var methodCRef = GetCRefIdentifier(methodBase);
                var model = new CodeDocMethod(methodCRef);
                model.Uri = GetUri(methodBase);

                var memberDataProvider = new CodeDocMemberInfoProvider<MethodBase>(methodBase);

                if (provideXmlDoc) {
                    var xmlDocs = XmlDocs.GetMember(methodCRef.FullCRef);
                    if (xmlDocs != null)
                        memberDataProvider.Add(new CodeDocMemberXmlDataProvider(xmlDocs));
                }

                if (extraMemberDataProvider != null)
                    memberDataProvider.Add(extraMemberDataProvider);

                if (includeInheritance && methodInfo != null) {
                    var baseDefinition = methodInfo.FindNextAncestor();
                    if (baseDefinition != null) {
                        var baseDefinitionModel = GetOnly(GetCRefIdentifier(baseDefinition), detailLevel);
                        if (baseDefinitionModel != null)
                            memberDataProvider.Add(new CodeDocMemberDataProvider(baseDefinitionModel));
                    }
                }

                if (appendXmlDoc)
                    ApplyContentXmlDocs(model, memberDataProvider);

                model.ExternalVisibility = memberDataProvider.ExternalVisibility ?? ExternalVisibilityKind.Public;
                model.ShortName = RegularTypeDisplayNameOverlay.GetDisplayName(methodBase);
                model.FullName = FullTypeDisplayNameOverlay.GetDisplayName(methodBase);
                model.Title = model.ShortName;
                Contract.Assume(methodBase.DeclaringType != null);
                model.NamespaceName = methodBase.DeclaringType.Namespace;

                if (includeParameters) {
                    model.Parameters = Array.ConvertAll(
                        methodBase.GetParameters(),
                        p => CreateArgument(p, memberDataProvider));

                    if (methodInfo != null && methodInfo.ReturnParameter != null &&
                        methodInfo.ReturnType != typeof (void))
                        model.Return = CreateReturn(methodInfo.ReturnParameter, memberDataProvider);
                }

                if (methodBase.IsConstructor)
                    model.SubTitle = "Constructor";
                else if (model.Parameters != null && model.Parameters.Count == 1 && model.HasReturn && CSharpOperatorNameSymbolMap.IsConversionOperatorMethodName(methodBase.Name)) {
                    model.SubTitle = "Conversion";

                    string conversionOperationName;
                    if (methodBase.Name.EndsWith("Explicit", StringComparison.OrdinalIgnoreCase))
                        conversionOperationName = "Explicit";
                    else if (methodBase.Name.EndsWith("Implicit", StringComparison.OrdinalIgnoreCase))
                        conversionOperationName = "Implicit";
                    else
                        conversionOperationName = String.Empty;

                    var conversionParameterPart = String.Concat(
                        model.Parameters[0].ParameterType.ShortName,
                        " to ",
                        model.Return.ParameterType.ShortName);

                    model.ShortName = String.IsNullOrEmpty(conversionOperationName)
                        ? conversionParameterPart
                        : String.Concat(conversionOperationName, ' ', conversionParameterPart);
                    model.Title = model.ShortName;
                }
                else if (methodBase.IsOperatorOverload())
                    model.SubTitle = "Operator";
                else
                    model.SubTitle = "Method";

                Contract.Assume(methodBase.DeclaringType != null);
                model.Namespace = GetOrCreateNamespaceByName(methodBase.DeclaringType.Namespace);
                model.Assembly = GetCodeDocAssembly(methodBase.DeclaringType.Assembly);
                model.DeclaringType = GetOrConvert(methodBase.DeclaringType, CodeDocMemberDetailLevel.Minimum);
                model.IsOperatorOverload = methodBase.IsOperatorOverload();
                model.IsExtensionMethod = methodBase.IsExtensionMethod();
                model.IsSealed = methodBase.IsSealed();
                model.IsStatic = memberDataProvider.IsStatic.GetValueOrDefault();
                model.IsObsolete = memberDataProvider.IsObsolete.GetValueOrDefault();
                model.IsPure = memberDataProvider.IsPure.GetValueOrDefault();

                if (methodBase.DeclaringType != null && !methodBase.DeclaringType.IsInterface) {
                    if (methodBase.IsAbstract)
                        model.IsAbstract = true;
                    else if (methodBase.IsVirtual && !methodBase.IsFinal && methodBase.Attributes.HasFlag(MethodAttributes.NewSlot))
                        model.IsVirtual = true;
                }

                if (includeExceptions){
                    if (memberDataProvider.HasExceptions)
                        model.Exceptions = CreateExceptionModels(memberDataProvider.GetExceptions()).ToArray();
                    if (memberDataProvider.HasEnsures)
                        model.Ensures = memberDataProvider.GetEnsures().ToArray();
                    if (memberDataProvider.HasRequires)
                        model.Requires = memberDataProvider.GetRequires().ToArray();
                }

                if (includeParameters && methodBase.IsGenericMethod) {
                    var genericDefinition = methodBase.IsGenericMethodDefinition
                        ? methodBase
                        : methodInfo == null ? null : methodInfo.GetGenericMethodDefinition();
                    if (genericDefinition != null) {
                        var genericArguments = genericDefinition.GetGenericArguments();
                        if (genericArguments.Length > 0) {
                            model.GenericParameters = CreateGenericTypeParameters(
                                genericArguments,
                                memberDataProvider);
                        }
                    }
                }

                return model;
            }
            protected CodeDocMethod ToMethodModel(ICodeDocMember member)
            {
                if (member == null)
                    return null;
                if (member is CodeDocMethod)
                    return (CodeDocMethod)member;

                var methodModel = new CodeDocMethod(member.CRef.WithTargetType("M"));

                var simpleMember = member as CodeDocSimpleMember;
                if (simpleMember != null)
                    CopySimpleMemberAttributes(methodModel, simpleMember);

                return methodModel;
            }
        /// <summary>
        /// Generates a model that is extracted from MTPS data.
        /// </summary>
        /// <param name="cRef">The code reference to search for.</param>
        /// <param name="searchContext">The search context for locating related items.</param>
        /// <param name="detailLevel">The desired detail level of the generated model.</param>
        /// <returns>A code doc member model if found.</returns>
        public ICodeDocMember GetMemberModel(CRefIdentifier cRef, CodeDocRepositorySearchContext searchContext = null, CodeDocMemberDetailLevel detailLevel = CodeDocMemberDetailLevel.Full)
        {
            if(cRef == null) throw new ArgumentNullException("cRef");
            Contract.EndContractBlock();

            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var tocResults = SearchToc(cRef.FullCRef);
            var bestTocResult = tocResults.FirstOrDefault();
            stopwatch.Stop();
            Debug.WriteLine("Search for {0} returned in {1}", cRef, stopwatch.Elapsed);

            if (bestTocResult == null)
                return null;

            Uri uri;
            if (!Uri.TryCreate(GetUrl(bestTocResult), UriKind.Absolute, out uri))
                uri = cRef.ToUri();

            CodeDocSimpleMember model = null;

            if (detailLevel != CodeDocMemberDetailLevel.Minimum) {
                var contentXml = GetContent(bestTocResult.ContentId);
                if (contentXml != null) {

                    bool? isSealed = null;
                    bool? isValueType = null;
                    bool? isReferenceType = null;
                    bool? isEnum = null;
                    bool? isVirtual = null;
                    bool? isAbstract = null;
                    bool? isMethod = null;
                    ExternalVisibilityKind? visibility = null;

                    var titleDiv = contentXml.GetElementsByTagName("div")
                        .OfType<XmlElement>()
                        .FirstOrDefault(x => "TITLE".Equals(x.GetAttribute("class"), StringComparison.OrdinalIgnoreCase));

                    if (titleDiv != null) {
                        var innerTitleText = titleDiv.InnerText.Trim();
                        if (innerTitleText.EndsWith("Method", StringComparison.OrdinalIgnoreCase)) {
                            isMethod = true;
                        }
                    }

                    var syntaxElement = contentXml.GetElementsByTagName("mtps:CollapsibleArea")
                        .OfType<XmlElement>()
                        .FirstOrDefault(x => "SYNTAX".Equals(x.GetAttribute("Title"), StringComparison.OrdinalIgnoreCase));
                    var codeSnippets = syntaxElement.GetElementsByTagName("mtps:CodeSnippet").OfType<XmlElement>().ToList();

                    foreach (var snippet in codeSnippets) {
                        var inputSpans = snippet.GetElementsByTagName("span")
                            .OfType<XmlElement>()
                            .Where(e => e.GetAttribute("class") == "input")
                            .ToList();
                        if (snippet.GetAttribute("Language") == "CSharp") {
                            foreach (var inputSpan in inputSpans) {
                                var innerText = inputSpan.InnerText;
                                if ("PUBLIC".Equals(innerText, StringComparison.OrdinalIgnoreCase))
                                    visibility = ExternalVisibilityKind.Public;
                                else if ("PROTECTED".Equals(innerText, StringComparison.OrdinalIgnoreCase))
                                    visibility = ExternalVisibilityKind.Protected;
                                else if ("SEALED".Equals(innerText, StringComparison.OrdinalIgnoreCase))
                                    isSealed = true;
                                else if ("CLASS".Equals(innerText, StringComparison.OrdinalIgnoreCase))
                                    isReferenceType = true;
                                else if ("STRUCT".Equals(innerText, StringComparison.OrdinalIgnoreCase))
                                    isValueType = true;
                                else if ("ENUM".Equals(innerText, StringComparison.OrdinalIgnoreCase))
                                    isEnum = true;
                                else if ("VIRTUAL".Equals(innerText, StringComparison.OrdinalIgnoreCase))
                                    isVirtual = true;
                                else if ("ABSTRACT".Equals(innerText, StringComparison.OrdinalIgnoreCase))
                                    isAbstract = true;
                            }
                        }
                    }

                    if (model == null) {
                        if (isReferenceType ?? isValueType ?? isEnum ?? false) {
                            var typeModel = new CodeDocType(cRef);
                            typeModel.IsSealed = isSealed;
                            typeModel.IsValueType = isValueType;
                            typeModel.IsEnum = isEnum;
                            model = typeModel;
                        }
                        else if (isMethod ?? false) {
                            var methodModel = new CodeDocMethod(cRef);
                            methodModel.IsSealed = isSealed;
                            methodModel.IsVirtual = isVirtual;
                            methodModel.IsAbstract = isAbstract;
                            model = methodModel;
                        }
                        else {
                            model = new CodeDocSimpleMember(cRef);
                        }
                        model.ExternalVisibility = visibility ?? ExternalVisibilityKind.Hidden;
                    }

                    XmlNode summaryElement = contentXml.GetElementsByTagName("div")
                        .OfType<XmlElement>()
                        .FirstOrDefault(x => String.Equals(x.GetAttribute("class"), "summary", StringComparison.OrdinalIgnoreCase));
                    if (summaryElement != null) {
                        if (summaryElement.ChildNodes.Count == 1 && summaryElement.ChildNodes[0].Name == "p") {
                            // unwrap the lone p tag.
                            summaryElement = summaryElement.ChildNodes[0];
                        }
                        var summaryXmlDoc = XmlDocParser.Default.Parse(summaryElement);
                        model.SummaryContents = summaryXmlDoc.Children;
                    }

                }

            }

            if (model == null)
                model = new CodeDocSimpleMember(cRef);

            if(model.ExternalVisibility == ExternalVisibilityKind.Hidden)
                model.ExternalVisibility = ExternalVisibilityKind.Public;

            model.Uri = uri;
            model.FullName = bestTocResult.GetFullName();

            int lastTitleSpaceIndex = bestTocResult.Title.LastIndexOf(' ');
            if (lastTitleSpaceIndex >= 0) {
                model.Title = bestTocResult.Title.Substring(0, lastTitleSpaceIndex);
                model.SubTitle = bestTocResult.Title.Substring(lastTitleSpaceIndex + 1);
            }
            else {
                model.Title = bestTocResult.Title;
                model.SubTitle = String.Empty;
            }
            model.ShortName = model.Title;

            if (String.IsNullOrEmpty(model.NamespaceName)) {
                MtpsNodeCore namespaceNode = bestTocResult;
                while (namespaceNode != null && !namespaceNode.IsNamespace) {
                    namespaceNode = namespaceNode.Parent;
                }
                if (namespaceNode != null) {
                    model.NamespaceName = namespaceNode.GetNamespaceName();
                    model.Namespace = GetNamespaceByName(model.NamespaceName);
                }
            }

            return model;
        }