{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "You must install **.NET Interactive Notebooks** extension in VS Code to run this notebook!\n",
        "\n",
        "Load the NuGet package and print out the version to make sure we are using the latest and greatest"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div><div></div><div></div><div><strong>Installed Packages</strong><ul><li><span>ICSharpCode.Decompiler, 8.1.0.7455</span></li></ul></div></div>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "ICSharpCode.Decompiler, Version=8.1.0.7455, Culture=neutral, PublicKeyToken=d4bfe873e7598c49\r\n"
          ]
        }
      ],
      "source": [
        "#r \"nuget: ICSharpCode.Decompiler, 8.1.0.7455\"\n",
        "\n",
        "using System.Reflection.Metadata;\n",
        "using ICSharpCode.Decompiler;\n",
        "using ICSharpCode.Decompiler.CSharp;\n",
        "using ICSharpCode.Decompiler.Metadata;\n",
        "using ICSharpCode.Decompiler.TypeSystem;\n",
        "\n",
        "Console.WriteLine(typeof(FullTypeName).Assembly.GetName());"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "You must have compiled **ILSpy.XPlat.slnf** first (run “dotnet build” in ICSharpCode.Decompiler.PowerShell folder). Make sure to modify **basePath** to your repository path."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [],
      "source": [
        "const string basePath = @\"D:\\GitWorkspace\\ILSpy\\\";\n",
        "string testAssemblyPath = basePath + @\"ICSharpCode.Decompiler.PowerShell\\bin\\Release\\netstandard2.0\\ICSharpCode.Decompiler.dll\";\n",
        "\n",
        "var decompiler = new CSharpDecompiler(testAssemblyPath, new DecompilerSettings());"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Get the count of types in this module"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "1532\r\n"
          ]
        }
      ],
      "source": [
        "var types = decompiler.TypeSystem.MainModule.TypeDefinitions;\n",
        "Console.WriteLine(types.Count());"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Decompile a known type (as a whole)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "using System;\r\n",
            "\r\n",
            "namespace ICSharpCode.Decompiler.Util;\r\n",
            "\r\n",
            "public static class Empty<T>\r\n",
            "{\r\n",
            "\tpublic static readonly T[] Array = System.Array.Empty<T>();\r\n",
            "}\r\n",
            "\r\n"
          ]
        }
      ],
      "source": [
        "// ICSharpCode.Decompiler.Util.Empty<T> -> translates to `n, where n is the # of generic parameters\n",
        "var nameOfGenericType = new FullTypeName(\"ICSharpCode.Decompiler.Util.Empty`1\");\n",
        "Console.WriteLine(decompiler.DecompileTypeAsString(nameOfGenericType));"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "If you want to decompile one single member (sample: first method)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "using System;\r\n",
            "\r\n",
            "static UniversalAssemblyResolver()\r\n",
            "{\r\n",
            "\tgac_paths = GetGacPaths();\r\n",
            "\tZeroVersion = new Version(0, 0, 0, 0);\r\n",
            "\tif (Type.GetType(\"Mono.Runtime\") != null)\r\n",
            "\t{\r\n",
            "\t\tdecompilerRuntime = DecompilerRuntime.Mono;\r\n",
            "\t}\r\n",
            "\telse if (typeof(object).Assembly.GetName().Name == \"System.Private.CoreLib\")\r\n",
            "\t{\r\n",
            "\t\tdecompilerRuntime = DecompilerRuntime.NETCoreApp;\r\n",
            "\t}\r\n",
            "\telse if (Environment.OSVersion.Platform == PlatformID.Unix)\r\n",
            "\t{\r\n",
            "\t\tdecompilerRuntime = DecompilerRuntime.Mono;\r\n",
            "\t}\r\n",
            "}\r\n",
            "\r\n"
          ]
        }
      ],
      "source": [
        "var nameOfUniResolver =  new FullTypeName(\"ICSharpCode.Decompiler.Metadata.UniversalAssemblyResolver\");\n",
        "ITypeDefinition typeInfo = decompiler.TypeSystem.FindType(nameOfUniResolver).GetDefinition();\n",
        "var tokenOfFirstMethod = typeInfo.Methods.First().MetadataToken;\n",
        "Console.WriteLine(decompiler.DecompileAsString(tokenOfFirstMethod));"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "If you need access to low-level metadata tables"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [],
      "source": [
        "ITypeDefinition type = decompiler.TypeSystem.FindType(nameOfUniResolver).GetDefinition();\n",
        "var module = type.ParentModule.PEFile;"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Get the child namespaces"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Microsoft\n",
            "System\n",
            "LightJson\n",
            "Humanizer\n",
            "ICSharpCode\n",
            "FxResources\n",
            "Internal\n",
            "MS\n"
          ]
        }
      ],
      "source": [
        "var icsdns = decompiler.TypeSystem.RootNamespace;\n",
        "foreach (var cn in icsdns.ChildNamespaces) Console.WriteLine(cn.FullName);"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Get types in a single namespace"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "LightJson.JsonArray\r\n"
          ]
        }
      ],
      "source": [
        "var typesInNamespace = icsdns.ChildNamespaces.First(cn => cn.FullName == \"LightJson\").Types;\n",
        "Console.WriteLine(typesInNamespace.First().FullTypeName);"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "dotnet_interactive": {
          "language": "csharp"
        },
        "vscode": {
          "languageId": "polyglot-notebook"
        }
      },
      "outputs": [],
      "source": []
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": ".NET (C#)",
      "language": "C#",
      "name": ".net-csharp"
    },
    "language_info": {
      "file_extension": ".cs",
      "mimetype": "text/x-csharp",
      "name": "csharp",
      "pygments_lexer": "csharp",
      "version": "8.0"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}