AOP without weaving

In this post I’ll present a usage of runtime method replacer in AOP context. The idea behind it is to change the behavior of an application without changing the IL of its methods. In this post I’ll show how to log an exception from a method.

This post is based on the work of Ziad Elmalki who posted the original method replacer. It is also based on the updated code for the method replacer by Chung Sung which is compatible with the new .NET framework versions. Lastly thanks to Roy Osherove who mentioned those recently.

Replacing methods

The method replacer uses the following concept – after a method is jitted it receives a pointer of the jitted code. You can see how to extract that address in the original post. After extracting the addresses, we can simply replace one method with another:

public static void ReplaceMethod(IntPtr srcAdr, IntPtr destAdr)
{
unsafe
{
if (IntPtr.Size == 8)
{
ulong* d = (ulong*)destAdr.ToPointer();
*d = (
ulong)srcAdr.ToInt64();
}
else
{
uint* d = (uint*)destAdr.ToPointer();
*d = (
uint)srcAdr.ToInt32();
}
}
}

As a simple example, if we have these two methods:

public class MyClass
{
public static void Foo()
{
Console.WriteLine("In Foo");
throw new Exception("I am done here!");
}

public static void Bar()
{
Console.WriteLine("In Bar");
}
}

Then executing Foo in the following context:

MethodInfo barMethod = typeof (MyClass).GetMethod("Bar");
MethodInfo fooMethod = typeof (MyClass).GetMethod("Foo");
MethodUtil.ReplaceMethod(barMethod, fooMethod);
MyClass.Foo();

Will actually lead to the next result:

image

Which is… Cool!

Catching exceptions in Foo

What I’d like to present is a simplified example of how to catch an exception in business code without modifying it. A similar functionality to PostSharp exception handling. What we’re about to do is to hijack the original calls to Foo and redirect those to our new wrapper method. Our new wrapper method will call the original one inside a try/catch block.

Storing the original Foo

Since we’re about to intercept calls to Foo based on its address, we’d like to store a “way” to call the original method later. The “way” to do it is simple, we’ll extract the method address before starting the interception and create a delegate to it using marshaling. The delegate will be stored on a field:

MethodInfo fooMethod = typeof (MyClass).GetMethod("Foo");
IntPtr fooAdress = MethodUtil.GetMethodAddress(fooMethod);
OriginalFoo =
Marshal.GetDelegateForFunctionPointer(fooAdress, typeof (Action));

Creating the wrapper

For the purpose of this example we could prepare a stub in the project istelf. But, in order to prove that it is likely possible to create a more general solution, we will generate the wrapper at runtime.

Since the wrapper is going to receive the calls instead of Foo it must have the same signature. Besides, our wrapper will retrieve the original Foo delegate from a static field named OriginalFoo. The delegate will be called from the method inside a try/catch block.

We will generate a dynamic method that replaces the original method:

// The field holding the delegate to the original Foo
FieldInfo originalFooDelegateField = typeof (FooProtector).GetField("OriginalFoo");

MethodInfo invokeDelegateMethod = OriginalFoo.GetType().GetMethod("DynamicInvoke");
MethodInfo innerExceptionGetter = typeof(Exception).GetProperty("InnerException").GetGetMethod();
MethodInfo exceptionMessageGetter = typeof(Exception).GetProperty("Message").GetGetMethod();

var dynamicMethod = new DynamicMethod("FooProtector", typeof(void), new Type[0]);
ILGenerator ilGenerator = dynamicMethod.GetILGenerator();

Label beginExceptionBlock = ilGenerator.BeginExceptionBlock();

// Preparing the call to the original Foo -
// Load the original Foo
ilGenerator.Emit(OpCodes.Ldsfld, originalFooDelegateField);
// Load "no arguments" to invoke the delegate
ilGenerator.Emit(OpCodes.Ldnull);
// Invoke the delegate and call original Foo
ilGenerator.Emit(OpCodes.Callvirt, invokeDelegateMethod);
ilGenerator.Emit(
OpCodes.Pop);

ilGenerator.Emit(
OpCodes.Leave, beginExceptionBlock);
ilGenerator.BeginCatchBlock(
typeof (Exception));

// Extract the exception message
ilGenerator.Emit(OpCodes.Callvirt, innerExceptionGetter);
ilGenerator.Emit(
OpCodes.Callvirt, exceptionMessageGetter);

// Print the exception message
MethodInfo info = typeof (Console).GetMethod("WriteLine", new[] {typeof (string)});
ilGenerator.Emit(
OpCodes.Call, info);

ilGenerator.Emit(
OpCodes.Leave, beginExceptionBlock);
ilGenerator.EndExceptionBlock();
ilGenerator.Emit(
OpCodes.Ret);

// Trigger method compilation
dynamicMethod.CreateDelegate(typeof (Action));

This wrapper calls the original method through a delegate. In case an exception is thrown, it extracts the original exception and prints to the console the message.

Is it working?

Let’s revisit the original code and update it to the protecting code:

FooProtector.ProtectFoo();
MyClass.Foo();

The expected result is two messages printed, where the second one is the exception message “I am done here!”. As we can happily see, this is the exact result:

image

Conclusion

The concept of replacing methods using their jitted versions can be useful. It can be used to for AOP where it can be used for logging, exception handling and basically applying any custom aspect. It can also be used to modify some 3rd party code behavior for which we have no source code. Additionally, as Roy says is can be used as an engine for mocking frameworks.

But there are some disadvantages too. Firstly, it is very dependent on the compilation outcome which makes it quite fragile. Secondly, it is sensitive to optimizations, for example inlined methods cannot be handled. Thirdly, when it is used extensively it requires generation and JIT of many dynamic methods which might lead to a performance hit.

Advertisement

Retrieving property value by name using dynamic method

In the previous post we compared some alternatives of the dynamic keyword. One important and very interesting alternative is based on reflection emit. Reflection emit enables us to generate code using IL at runtime, compile it and execute it straightaway.
In this post we’ll see how to extract a string property named ‘Name’ from an unknown type using a dynamic method.

The code

public static string GetNameByDynamicMethod(object arg)
{
Type type = arg.GetType();

Func<object, string> getterDelegate;
if (!typeToEmitDelegateMap.TryGetValue(type, out getterDelegate))
{
string typeName = type.Name;

PropertyInfo nameProperty = type.GetProperty("Name");
Type returnType = typeof (string);

// Define a new dynamic method
// The method returns a string type
// The method expects single parameter
var method = new DynamicMethod("GetNameFrom" + typeName,
returnType,
new[] {typeof(object)});

ILGenerator ilGenerator = method.GetILGenerator();

// Load to the stack the first method argument.
//In our case, this is an object whose type we already know
ilGenerator.Emit(OpCodes.Ldarg_0);

// Cast the object to the type we already know
ilGenerator.Emit(OpCodes.Castclass, type);

// Call the getter method on the casted instance
ilGenerator.EmitCall(OpCodes.Call, nameProperty.GetGetMethod(), null);

// Return the value from Name property
ilGenerator.Emit(OpCodes.Ret);

// Compile the method and create a delegate to the new method
getterDelegate = (Func<object, string>)method.CreateDelegate(typeof(Func<object, string>));

typeToEmitDelegateMap.Add(type, getterDelegate);
}

return getterDelegate(arg);
}

What we did here was to define a new method, generate its code with IL, compile it and execute it. This new method is equivalent in many ways to a method we had generated in the original program. This new method will be hosted in a dynamic module in the memory.

The advantage of this kind of method over reflection is that it compiles the code once and doesn’t need to explore the type again whenever we need to get the property value.

Performance

A quick comparison for calling these alternatives 10,000,000 times each:

Seconds Ratio to directly
Directly 0.0131 1
Dynamic 0.4609 35
Expression 0.9154 70
Reflection emit 0.9832 75

As can be seen, using the dynamic keyword works much faster than compiling an expression or a dynamic method at runtime.

Another interesting data set shows the time that each alternative takes to set up (The time to perform the first call):

Seconds
Directly 0.00003
Dynamic 0.08047
Expression 0.00114
Reflection emit 0.02169