6

Using the Roslyn API with Visual Studio 2015, can I convert an object instance to source code? Can I create an extension method like ".ToSourceCode()" as shown below?

class Foo { }
class Program
{
    static string classSourceCode = "class Foo { }";
    static void Main()
    {
        var instance = new Foo();
        var instanceSourceCode = instance.GetType().ToSourceCode();
        System.Diagnostics.Debug.Assert(instanceSourceCode == classSourceCode);
    }
}
17
  • Didn't took a look to Rslyn yet, but if that's possible then hacking ANY .net program would be just a matter of 5 minutes... Commented Apr 10, 2015 at 17:39
  • Yes, you certainly can write such a method. It is not built into Roslyn and there is little in Roslyn to help you with this. Commented Apr 10, 2015 at 17:39
  • 1
    yes or no questions make poor stack overflow questions. What research have you done about Roslyn's capabilities? What have you tried that failed and what errors are you getting that are different than your expected behavior. Commented Apr 10, 2015 at 17:39
  • 1
    Using "ToSourceCode" isn't the hard part, the hard part is WRITING "ToSourceCode". Commented Apr 10, 2015 at 17:45
  • 1
    @Robin the question is borderline on topic here. Yes/no is not the kind of question that is allowed here. So the question should be "How to write a ToSourceCode method?". But that is too broad because it kind of requires a tutorial or CodeProject article. Commented Apr 10, 2015 at 17:57

1 Answer 1

13

No. However, ILSpy can.

Based on the comments on the question and what I understand about Roslyn, decompilation is not supported. However, thanks to @Bradley's ILSpy tip, there is a solution:

  1. Download the ILSpy binaries from http://ilspy.net/
  2. Reference the following assemblies: ICSharpCode.Decompiler.dll, ILSpy.exe, Mono.Cecil.dll, ILSpy.BamlDecompiler.Plugin.dll
  3. Implement the ".ToSourceCode()" extension method as shown below:
using System;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy;
using Mono.Cecil;
class Foo { }
class Program
{
    static string classSourceCode = "using System; internal class Foo { } ";
    static void Main()
    {
        var instance = new Foo();
        var instanceSourceCode = instance.GetType().ToSourceCode();
        System.Diagnostics.Debug.Assert(instanceSourceCode == classSourceCode);
    }
}

static class TypeExtensions
{
    public static string ToSourceCode(this Type source)
    {
        var assembly = AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
        var type = assembly.MainModule.Types.FirstOrDefault(t => t.FullName == source.FullName);
        if (type == null) return string.Empty;
        var plainTextOutput = new PlainTextOutput();
        var decompiler = new CSharpLanguage();
        decompiler.DecompileType(type, plainTextOutput, new DecompilationOptions());
        return Regex.Replace(Regex.Replace(plainTextOutput.ToString(), @"\n|\r", " "), @"\s+", " ");
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Robin is absolutely correct. ILSpy is a better example of an analyzer for already-compiled code, which is now in IL form. If you use his/her example, then keep in mind that in order to recompile you'll need to also decompile or reference all of that object's types that it references - both in internal implementation or part of its signatures (e.g. supertypes, return types, parameter types). Roslyn is intended for analysis of C# and VB source code, though has facilities for understanding signatures from referenced IL assemblies, but not the method implementations.
Great answer! I would define assembly like this var assembly = AssemblyDefinition.ReadAssembly(Assembly.GetAssembly(source).Location); in order to make it work even when the type is defined in somewhere else.
hey @Robin do you find how to decompile an actual object instance to C# source code, and not a type definition? Give class Foo { public baa { get; set; } public int n { get; set; } } then var f = new Foo { baa = "str", n = 10 }; then a call to imaginary-decompile function decompile(f) would emit the very same C# source code: var f = new Foo { baa = "str", n = 10 };. The CSharpLanguage seems to decompile types only.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.