Cecil Feed 3
I’ve promised, here are some news of Mono.Cecil :
Mono.Cecil is now a top level module of Mono’s Subversion repository. It may be accessible from here, once the module will be mirrored to the anonymous SVN.
Included in the module is a little Gtk# Application, Cecil Feed, that for now, is just a modification of one of the samples bundled with Gtk#. The old sample was simply looking into assemblies, and diplayed some of their contents in a TreeView. I’ve juste adapted the sample and here is a screen shot of the beast :
And for curious peoples, here is the source of this sample application :
<span class="rem">// TreeView.cs - Fun TreeView demo</span>
<span class="rem">//</span>
<span class="rem">// Author: Kristian Rietveld <kris@gtk.org></span>
<span class="rem">//</span>
<span class="rem">// (c) 2002 Kristian Rietveld</span>
<span class="rem">// A rewrite of the TreeView demo using Cecil</span>
<span class="rem">// Author: Jb Evain <jb@evain.net></span>
<span class="kwrd">namespace</span> Cecil.Feed {
<span class="kwrd">using</span> System;
<span class="kwrd">using</span> Gtk;
<span class="kwrd">using</span> Mono.Cecil;
<span class="kwrd">public</span> <span class="kwrd">class</span> TreeViewDemo : IReflectionStructureVisitor {
<span class="kwrd">private</span> <span class="kwrd">string</span> m_file;
<span class="kwrd">private</span> TreeStore m_store = <span class="kwrd">null</span>;
<span class="kwrd">private</span> <span class="kwrd">int</span> m_count = 0;
<span class="kwrd">private</span> TreeIter m_cursor;
<span class="kwrd">private</span> <span class="kwrd">bool</span> m_newBranch = <span class="kwrd">false</span>;
<span class="kwrd">private</span> <span class="kwrd">bool</span> m_root = <span class="kwrd">true</span>;
<span class="kwrd">public</span> TreeViewDemo(<span class="kwrd">string</span> file) {
m_file = file;
DateTime start = DateTime.Now;
Application.Init ();
PopulateStore ();
Window win = <span class="kwrd">new</span> Window(<span class="str">"Cecil ~ Feed"</span>);
win.DeleteEvent += <span class="kwrd">new</span> DeleteEventHandler(<span class="kwrd">this</span>.DeleteCB);
win.SetDefaultSize(640,480);
ScrolledWindow sw = <span class="kwrd">new</span> ScrolledWindow ();
win.Add (sw);
TreeView tv = <span class="kwrd">new</span> TreeView(m_store);
tv.HeadersVisible = <span class="kwrd">true</span>;
tv.EnableSearch = <span class="kwrd">false</span>;
tv.AppendColumn (<span class="str">"Name"</span>, <span class="kwrd">new</span> CellRendererText (), <span class="str">"text"</span>, 0);
tv.AppendColumn (<span class="str">"Type"</span>, <span class="kwrd">new</span> CellRendererText (), <span class="str">"text"</span>, 1);
sw.Add (tv);
win.ShowAll ();
Console.WriteLine (m_count + <span class="str">" nodes added."</span>);
Console.WriteLine (<span class="str">"Startup time: "</span> + DateTime.Now.Subtract (start));
Application.Run ();
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IAssemblyDefinition asm) {
AddToTree(m_file, <span class="str">"AssemblyDefinition"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IAssemblyName name) {
AddToTree(name.FullName, <span class="str">"AssemblyName"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IAssemblyNameReferenceCollection names) {
m_newBranch = <span class="kwrd">false</span>;
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IAssemblyNameReference name) {
AddToTree(name.FullName, <span class="str">"AssemblyNameReference"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IResourceCollection resources) {
m_newBranch = <span class="kwrd">false</span>;
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IEmbeddedResource res) {
AddToTree(res.Name, <span class="str">"EmbeddedResource"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(ILinkedResource res) {
AddToTree(res.Name, <span class="str">"LinkedResource"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IModuleDefinition module) {
AddToTree(module.Name, <span class="str">"ModuleDefinition"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IModuleDefinitionCollection modules) {
m_newBranch = <span class="kwrd">true</span>;
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IModuleReference module) {
AddToTree(module.Name, <span class="str">"ModuleReference"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Visit(IModuleReferenceCollection modules) {
m_newBranch = <span class="kwrd">false</span>;
}
<span class="kwrd">private</span> <span class="kwrd">void</span> PopulateStore () {
m_store = <span class="kwrd">new</span> TreeStore (<span class="kwrd">typeof</span> (<span class="kwrd">string</span>), <span class="kwrd">typeof</span> (<span class="kwrd">string</span>));
IAssemblyDefinition asm = AssemblyFactory.GetAssembly(m_file);
asm.Accept(<span class="kwrd">this</span>);
}
<span class="kwrd">private</span> <span class="kwrd">void</span> AddToTree(<span class="kwrd">string</span> name, <span class="kwrd">string</span> type) {
<span class="kwrd">if</span> (m_newBranch) {
m_cursor = m_store.AppendValues(m_cursor, name, type);
m_newBranch = <span class="kwrd">false</span>;
} <span class="kwrd">else</span> {
m_store.AppendValues(m_cursor, name, type);
}
<span class="kwrd">if</span> (m_root) {
m_cursor = m_store.AppendValues(name, type);
m_root = <span class="kwrd">false</span>;
}
m_count++;
}
<span class="kwrd">private</span> <span class="kwrd">void</span> DeleteCB(<span class="kwrd">object</span> o, DeleteEventArgs args) {
Application.Quit ();
}
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Main (<span class="kwrd">string</span>[] args) {
<span class="kwrd">if</span> (args.Length == 0) {
Console.WriteLine(<span class="str">"usage: cecil-feed.exe assembly"</span>);
<span class="kwrd">return</span>;
}
<span class="kwrd">try</span> {
TreeViewDemo tvd = <span class="kwrd">new</span> TreeViewDemo(args[0]);
} <span class="kwrd">catch</span> (Exception e) {
Console.WriteLine(e);
}
}
}
}
Ok, it is very simple, but once I’ll work on Cecil a bit more, we can imagine to have here on the first Open Source ildasm clone. By the way, this example shows how it is simple with the design pattern visitor to walk through Cecil’s objects. Using this, it should be very easy to write some little tools like peverify, or even write optimizers.
What do you think you would do with a library to manipulate CIL files ?
Trackbacks
Use the following link to trackback from your own site:
http://www.evain.net/blog/articles/trackback/8
an Aspect Weaver ? :)
Nice job man, it’s amazing !
Looks very cool. I’m just wondering if the intention is to provide a complete relfection – like interface to the metadata/il in an assembly ? – ie TypeInfo, MethodInfo like structures. Is the way the ReflectionReader. The commented collection types in CodeGen/cecil.xml seems to indicate that this is intended but just hasn’t been implemented yet – is that correct ?
I’d like to be able to use somthing like this as a replacement for the reflection api such that assemblies don’t need to be loaded by the runtime.
Juste pour préciser que les news passent très mal sur l’aggrégateur de mono : y’a pas de retour à la ligne, pas de photo, enfin c’est illisible :)