internal TypeDeobfuscator(XElement typeNode)
        {
            m_comparer     = StringComparer.Ordinal;
            ObfuscatedName = ((string)typeNode.Element("newname")).Replace('/', '+');
            OriginalName   = ((string)typeNode.Element("name")).Replace('/', '+');
            var declaringType = TypeNameRegex.ParseType(OriginalName);

            m_fields = (from fieldNode in typeNode.Elements("fieldlist").Elements("field")
                        let originalName = (string)fieldNode.Element("name")
                                           let obfuscatedName = (string)fieldNode.Element("newname")
                                                                select new ObfuscatedField(obfuscatedName, originalName, declaringType)).ToArray();

            m_methods = typeNode.Elements("methodlist").Elements("method").Select(m =>
            {
                string originalName   = (string)m.Element("name");
                String obfuscatedName = (string)m.Element("newname");
                TypeName returnType   = default(TypeName);
                string prefix;
                TypeName[] args;
                string sig = (string)m.Element("signature");
                if (TypeNameRegex.TryExtractMethodInfo(sig.Replace('/', '+'), out prefix, out args))
                {
                    if (!string.IsNullOrEmpty(prefix))
                    {
                        returnType = TypeNameRegex.ParseType(prefix);
                    }
                }
                //TypeName returnType = null;
                return(new ObfuscatedMethod(obfuscatedName, originalName, returnType, args));
            }).ToArray();

            Array.Sort(m_fields, (left, right) => m_comparer.Compare(left.ObfuscatedName + left.DeclaringType, right.ObfuscatedName + right.DeclaringType));
            Array.Sort(m_methods, (left, right) => m_comparer.Compare(left.SortKey, right.SortKey));
        }
        public string DeobfuscateCallstack(string callstack)
        {
            string[] lines = callstack.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i];
                if (!line.Contains("System.Obfuscation"))
                {
                    continue;
                }
                string     prefix;
                TypeName[] args;
                if (TypeNameRegex.TryExtractMethodInfo(line, out prefix, out args))
                {
                    string declaringType = prefix.Substring(0, prefix.LastIndexOf("."));
                    string deObfType     = DeobfuscateSimpleType(declaringType);

                    string methodName = prefix.Substring(declaringType.Length + 1);
                    for (int j = 0; j < args.Length; j++)
                    {
                        string before = args[j].Name;
                        args[j] = DeobfuscateType(args[j]);
                        if (before == args[j].Name)
                        {
                            if (TypeNameRegex.CouldBeNestedType(args[j].Name))
                            {
                                //try as nested type.....
                                var arg2 = declaringType + "+" + args[j].Name;
                                var arg3 = DeobfuscateSimpleType(arg2);
                                if (arg2 != arg3)
                                {
                                    args[j] = new TypeName(arg3);
                                }
                            }
                        }
                    }
                    var obf = GetTypeDeobfuscator(declaringType);
                    if (obf != null)
                    {
                        List <ObfuscatedMethod> matches;
                        if (obf.TryDeobfuscateMethod(methodName, args.Select(a => a.ToString()).ToArray(), out matches))
                        {
                            if (matches.Count == 1)
                            {
                                lines[i] = $"{deObfType}.{matches[0].OriginalName}({string.Join(",", args)})";
                            }
                            else
                            {
                                var options = matches.Select(m => $"{deObfType}.{m.OriginalName}({string.Join(",", args)})");
                                lines[i] = "--AMBIGUOUS--\r\n\t" + string.Join("\r\n\t", options);
                            }
                        }
                    }
                }
            }
            return(string.Join(Environment.NewLine, lines));
        }
        public string DeobfuscateType(string obfuscatedTypeName)
        {
            var typeName = TypeNameRegex.ParseType(obfuscatedTypeName);

            if (typeName.Name != null)
            {
                return(DeobfuscateType(typeName).ToString());
            }

            return(obfuscatedTypeName);
        }
        public string ObfuscateType(string deobfuscatedTypeName)
        {
            TypeName typeInfo = TypeNameRegex.ParseType(deobfuscatedTypeName);

            if (typeInfo.Name != null)
            {
                var obf = ObfuscateType(typeInfo);
                return(obf.ToString());
            }
            return(deobfuscatedTypeName);
        }