Rhino Mocks 2.6

time to read 4 min | 644 words

Okay, there is a new version on the site, with a couple of bug fixes:

  • Support for methods that start with get_ & set_ that are not properties.
  • Fixed BackToRecord() not cleaning up repeatable expectation (read: SetupResult).
  • Added Is.TypeOf<int>() to save some typing.

This was suppose to be the version that would bring the ability to mock generic methods like Crete<T>(), unfortantely, even though Jeff supplied a code sample that showed the way (and I learned a whole lot more about the way generics work), it turn out to be a little more complicated than that.

I'm going to get deep into Dynamic Proxy internals, so if you don't care about that, you can here here and get the source / binaries. If you want to play with the source, be sure to use the latest version of Dynamic Proxy.

Now for the story, and a little background on the way Dynamic Proxy works:

When Dynamic Proxy needs to Proxy a type, it dynamically generate a subclass of this class (or a class that implements that interface), and redirect all its methods to an interceptor. Now, since it needs to be able to send the method call back to the original class, it need some way to do it that is supported by the runtime, the way it do that is by creating custom delegates that match the signature of each method that is proxied. Yes, this is a horrible explanation, but here is a mockup of the result of the generation:

public class ProxyOfFactory : Factory
{
    IInterceptor _interceptor;
     public delegate object __delegate__for_Create(string type);
     public ProxyOfIFactory(IInterceptor interceptor)
    { 
         _interceptor = interceptor;
    }

     public object Create(string type)
     {
           IInvocation invocation = new InterfaceMethodInvocation(this,
                     new __delegate_for_Create(base.Create));
           _interceptor.Call(invocation);
     }
}

Again, this is a highly simplistic view of the process, which mostly cannot be expressed in any langauge but IL. The issue with generic methods is that they require a lot of changes in a lot of places, the delegate needs to be generic, the method need to be generic, the call to the base class method need to be generic, etc. I focused solely on generating the methods that I forgot that I need to generate the delegates as well. And it gets very complicated very fast, especially when you're working with IL. There are currently plans to re-write Dynamic Proxy from scratch, and generic methods are part of the planned features, so I think I'll wait until we have the new version to add that support for Rhino Mocks.