The CCI code is somewhere between the IL disassembler and the full C # decompiler: it gives your code some structure (like if expressions and expressions), but also contains some low-level stack operations like push and pop .
CCI contains a sample that shows this: PeToText .
For example, to get the code model for the first method of type Program (in the global namespace), you can use this code:
string fileName = "whatever.exe"; using (var host = new PeReader.DefaultHost()) { var module = (IModule)host.LoadUnitFrom(fileName); var type = (ITypeDefinition)module.UnitNamespaceRoot.Members .Single(m => m.Name.Value == "Program"); var method = (IMethodDefinition)type.Members.First(); var methodBody = new SourceMethodBody(method.Body, host, null, null); }
To demonstrate, if you decompile the above code and show it with PeToText, you will get:
Microsoft.Cci.ITypeDefinition local_3; Microsoft.Cci.ILToCodeModel.SourceMethodBody local_5; string local_0 = "C:\\code\\tmp\\nuget tmp 2015\\bin\\Debug\\nuget tmp 2015.exe"; Microsoft.Cci.PeReader.DefaultHost local_1 = new Microsoft.Cci.PeReader.DefaultHost(); try { push (Microsoft.Cci.IModule)local_1.LoadUnitFrom(local_0).UnitNamespaceRoot.Members; push Program.<>c.<>9__0_0; if (dup == default(System.Func<Microsoft.Cci.INamespaceMember, bool>)) { pop; push Program.<>c.<>9.<Main0>b__0_0; Program.<>c.<>9__0_0 = dup; } local_3 = (Microsoft.Cci.ITypeDefinition)System.Linq.Enumerable.Single<Microsoft.Cci.INamespaceMember>(pop, pop); local_5 = new Microsoft.Cci.ILToCodeModel.SourceMethodBody((Microsoft.Cci.IMethodDefinition)System.Linq.Enumerable.First<Microsoft.Cci.ITypeDefinitionMember>(local_3.Members).Body, local_1, (Microsoft.Cci.ISourceLocationProvider)null, (Microsoft.Cci.ILocalScopeProvider)null, 0); } finally { if (local_1 != default(Microsoft.Cci.PeReader.DefaultHost)) { local_1.Dispose(); } }
All those push , pop and dup statements and the lambda cache condition should be noted.
svick source share