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 ?
DotNetGuru contributes to Mono, or the contrary 5
<span class="kwrd">using</span> Mono.Cecil;
Tonight, Cecil will leave SourceForge’s CVS to a better place, in the sun.
Cecil’s development will now be supported by Mono’s SVN. By the way, its name change a little bit. It is now Mono.Cecil, hey, sounds good no ?
Thanks to Miguel De Icaza, I have received a write access to Mono’s SVN last night. Cecil will be a top module until it is mature enough to be bundled with others Mono’s assemblies.
I’m proud, but a lot of work remains, Cecil isn’t really usable, but I hope that its new status will improve the speed of the devel, and will bring more feedbacks and bugs reports.
Last but not least, this blog may be syndicated within the Monologue, by this way the world may discovers AspectDNG, and others DNG activities I’ll blog on.
I’ll post as soon as migration is ended, to give you instructions to access Cecil’s repository. I may blog later on some screen shots of a little Gtk# application, using Cecil, that mimics ildasm, but it is really simple and limited to Cecil progress.
Isn’t the year 2005 beginning very well ?
new DotNetIde("x-develop"); 1
This morning Hans Cratz announced in the Mono Devel List the preview release of the new x-develop IDE.
I’m currently trying it, and you know what ? I’m happy. I’m switching my current development to it, just to see. At least it seems to be very promising. I have to admit I’m a bit jealous, it seems that I’m not the only one to want an Eclipse#. Yes, it is cross platform, and if I’ve not tried it under my Linux box, be sure I will.
Here is a quote from the mail :
Feature showcase:
- Instant detection of errors throughout all files
No need to compile in order to find out if there are errors. X-develop checks all files in the solution on-the-fly in the background and displays errors in an instant.
- Refactoring
X-develop includes refactorings for renaming variables, methods, classes, changing method signature, extracting methods and more.
- Productivity features
X-develop boosts productivity with coding tools such as Organize imports, Usage search, Code formatting, Smart templates, Go to class, Go to symbol and more.
- VS.net 2005 compatibility
X-develop uses the solutio/project concept from VS.net 2005. Solutions/projects created for Windows can be loaded and modified with X-develop on Linux.
It rocks. I’m now playing with code templates, code metrics. There is a lot of good stuff in this. I’ve not enough time to write a complete review of it, but it’s an interesting article idea for DNG.
Go, try it, and make your own idea. My question now is will it be free ?
Some links :
Edit
I was so excited that I did not even notice that it is written in Java, but does it cares ? A little, I think an Eclipse# written in .net should be a very exciting thing.
Type 6 IOC, weaving the dependency 4
Everybody’s gone weavin’,
Weavin’ D.N.G. !
Life is a beach, let’s try a new meta aspect : ReplaceConstructorCall, and by the way, discover a new type of IOC, not constructor based, not setter based, everything is done by AspectDNG. Maybe this is not even IOC. Don’t care, it’s cool.
I’ve written this today, it’s some kind of proof of concept. It is in CVS now, but maybe it will evolve or change. IOC is one buzz word of today. In one of his (famous) article, in French, and in English, Sami Jaber describes 3 types of commonly used IOC, interface based, getter based, and constructor based. I have named this blog entry after this article on tss. Mainly because I’m not really serious. However, I think that AOP may “eclipse” IOC.
An example is coming.
The beginning, a very simple set of base classes :
<span class="rem">// base.cs</span>
<span class="kwrd">namespace</span> AspectDNG.Sample {
<span class="kwrd">public</span> <span class="kwrd">interface</span> IComplexSystem {
<span class="kwrd">void</span> DoTheWholeThing(<span class="kwrd">string</span> a);
}
<span class="kwrd">public</span> <span class="kwrd">class</span> MockSystem : IComplexSystem {
<span class="kwrd">public</span> MockSystem() {}
<span class="kwrd">public</span> <span class="kwrd">void</span> DoTheWholeThing(<span class="kwrd">string</span> a) {}
}
<span class="kwrd">public</span> <span class="kwrd">class</span> Pono {
<span class="kwrd">private</span> <span class="kwrd">string</span> m_a;
<span class="kwrd">private</span> IComplexSystem m_system = <span class="kwrd">new</span> MockSystem();
<span class="kwrd">public</span> Pono(<span class="kwrd">string</span> a) {
m_a = a;
}
<span class="kwrd">public</span> <span class="kwrd">void</span> TryTheThing() {
m_system.DoTheWholeThing(m_a);
}
}
<span class="kwrd">public</span> <span class="kwrd">class</span> EntryPoint {
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args) {
Pono p = <span class="kwrd">new</span> Pono(<span class="str">"HELLO IOC6 !"</span>);
p.TryTheThing();
}
}
}
What can we see there ? An interface, describing a complex system we want to use, then a Mock object, that may be avoided, but that is there for type safety, and for bookmarking. After this you find a plain old .net object, that depends on our complex system. The entry point creates the Pono object, and ask him to call its dependency. If you compile that and call it, nothing will happens. Let’s weave the dependencies ! Here is my aspect :
<span class="rem">// aspect.cs</span>
<span class="kwrd">namespace</span> AspectDNG.Sample {
<span class="kwrd">using</span> AspectDNG;
[Insert(<span class="str">"module:"</span>)]
<span class="kwrd">public</span> <span class="kwrd">class</span> RealComplexSystem : IComplexSystem {
[ReplaceConstructorCall(<span class="str">"* *.MockSystem::.ctor()"</span>)]
<span class="kwrd">public</span> RealComplexSystem() {}
<span class="kwrd">public</span> <span class="kwrd">void</span> DoTheWholeThing(<span class="kwrd">string</span> a) {
System.Console.WriteLine(a.ToLower());
}
}
}
This is a concrete implementation of my complex service. I use custom attributes to describe that I want RealComplexSystem to be
inserted in the main module of the target assembly, and I use my new ReplaceConstructorCall. It’s explicit, every call to the constructor
of MockSystem will be replaced by the constructor of RealComplexSystem. It rocks no ?If I execute this, my complex system will do its job :
D:/temporary/adng>AspectDNG -dw base.exe aspect.dll D:/temporary/adng>base hello ioc6 ! D:/temporary/adng>
So, what do you think about this ?