Mono.Linq.Expressions 2
In the same vein of my little Mono.Reflection library, which complements the System.Reflection namespace with useful features such as an IL disassembler, Mono.Linq.Expressions is a small library for everyone who has to manipulate LINQ Expression Trees.
The first feature I’ve been adding is a simple pretty printer for expression trees. It comes in handy whenever you want a textual representation of an expression tree in a language you know.
For instance, let’s imagine you’re calling a method returning an expression:
Expression<Func<int, int, int>> silly = GetSillyExpression ();
And you want to quickly have a look at what it does. You may as well use a good old Console.WriteLine, but here’s what it will print:
(a, b) => IIF((a > b), {var c; ... }, {var d; ... })
Yeah right. Not very useful isn’t it. So let’s use your internal knowledge of the DLR and print its DebugView:
.Lambda #Lambda1<System.Func`3[System.Int32,System.Int32,System.Int32]>(
System.Int32 $a,
System.Int32 $b) {
.If ($a > $b) {
.Block(System.Int32 $c) {
$c = $a #+ $b;
$c #+= 42;
$c
}
} .Else {
.Block(System.Int32 $d) {
$d = $a #- $b;
$d #-= 42;
$d
}
}
}
Better yet. But it doesn’t look even remotely familiar. Here comes Mono.Linq.Expressions.
Let’s call Console.WriteLine once more, but in a slightly different way:
Console.WriteLine (silly.ToCSharpCode ());
And here’s the output:
int (int a, int b)
{
if (a > b)
{
int c;
c = checked { a + b };
checked { c += 42 };
return c;
}
else
{
int d;
d = checked { a - b };
checked { d -= 42 };
return d;
}
}
Now I get it! And it’s indeed plain silly. But that’s not the point.
If you’re implementing a language on top of the DLR, or playing with the new keyword dynamic’s innards, or writing a LINQ provider, you might find it useful.
Mono.Cecil 0.9.2
I tagged Mono.Cecil 0.9.2 at the beginning of the week in Cecil’s github. It’s a bug fix release, exactly two weeks after the release of 0.9.1.
It’s fast, stable, and shiny, thanks to all the contributors and testers of the 0.9 line. It’s safe to say that users of the 0.6 line of code are urged to update to this version, and report issues, if any.
parameterof, propertyof, methodof 8
Every C# programmer knows about the keyword typeof, in essence, it returns an instance of System.Type for a given type. It’s used everywhere you have to do reflection on a type known at compilation time. You could achieve pretty much the same with the methods GetType(string) of both Module and Assembly, but the nice thing about typeof is that it’s refactoring proof.
Now, every C# programmer also knows that typeof is the only keyword with such abilities. There’s no parameterof, propertyof, methodof, or eventof to access other metadata members. The web is filled with ways to emulate a type safe reflection though. Lately, expression trees helped a lot. This post presents a proof of concept piece of code for a different approach.
Considering the following types:
public static class Parameter {
public static ParameterInfo Of<T> (T value)
{
return null;
}
}
public static class Property {
public static PropertyInfo Of<T> (T value)
{
return null;
}
public static PropertyInfo Of (MethodInfo method)
{
const BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
foreach (var property in method.DeclaringType.GetProperties (all))
if (method.Equals (property.GetGetMethod (true)))
return property;
return null;
}
}
public static class Method {
public static MethodInfo Of<T> (Func<T> value)
{
return null;
}
public static MethodInfo Of<T1, TRet> (Func<T1, TRet> value)
{
return null;
}
public static MethodInfo Of (Action value)
{
return null;
}
public static MethodInfo Of<T> (Action<T> value)
{
return null;
}
}
They are basically just stubs, but let’s use them anyway:
class Program {
static void Main (string [] args)
{
ParameterInfo parameter = Parameter.Of (args);
Console.WriteLine ("Parameter of args: {0}", parameter);
PropertyInfo rank = Property.Of (args.Rank);
Console.WriteLine ("Property of rank: {0}", rank);
MethodInfo foo = Method.Of<int> (Foo);
Console.WriteLine ("Foo method: {0}", foo);
MethodInfo bar = Method.Of<int> (Bar);
Console.WriteLine ("Bar method: {0}", bar);
}
static int Foo ()
{
return 42;
}
static void Bar (int b)
{
return;
}
}
Of course if you run the code as is, everything will be null. What I did is that I wrote a little Cecil rewriter that will detect the calls to the different Of methods, and rewrite them to something that will give you the expected results.
So for instance, the Parameter.Of call is compiled as:
ldarg.0 call class [mscorlib]System.Reflection.ParameterInfo Parameter::Of<string[]>(!!0)
But is rewritten in two parts. First we emit at the beginning of the method a way to retrieve of the ParameterInfo of the current method:
ldtoken method void Program::Main(string[]) call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle) callvirt instance class [mscorlib]System.Reflection.ParameterInfo[] [mscorlib]System.Reflection.MethodBase::GetParameters() stloc $reflection_parameters
And we simple replace the Of call with a load from the $reflection_parameters array:
ldloc $reflection_parameters ldc.i4 0 ldelem.ref
For methods it’s a bit different, they are compiled as:
ldnull ldftn int32 Program::Foo() newobj instance void class [mscorlib]System.Func`1<int32>::.ctor(object,native int) call class [mscorlib]System.Reflection.MethodInfo Method::Of<int32>(class [mscorlib]System.Func`1<!!0>)
And we rewrite them to remove the creation of a delegate:
ldtoken method int32 Program::Foo() call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle) castclass [mscorlib]System.Reflection.MethodInfo
For properties, it’s exactly the same, but we have to inject a call to a method that will retrieve the PropertyInfo the get method belongs to.
If you’re interested you can read the rewriter code. It’s pretty simple, but is nowhere complete, and I doubt anyone would use it anyway, but it’s still a pretty cool hack.
Mono.Cecil 0.9.1
I pushed to my github repository an update for Mono.Cecil. It contains a week worth of fixes reported by the folks who ported their code to use the new API. The main addition for this release is the support for complex types in custom attributes, which was pretty much the only known thing that was not supported in 0.9, metadata wise.
Thanks to everyone that took the time to update to 0.9 and report issues.
