Unity’s VirtualMethodInterceptor with internal classes

December 13th, 2009 by Andy Leave a reply »

Unity includes some basic AOP functionality.  One of the interception mechanisms it offers is VirtualMethodInterceptor, which works by building a derived class at runtime and overriding the virtual methods of the target class.  This approach has some obvious limitations, but it seemed like a good way to handle some simple logging & profiling requirements that I have with my current project.

The first problem I hit is that the current release of Unity (1.2) has a huge bug – VirtualMethodInterceptor doesn’t work with classes that have parameters in their constructors.  Fortunately downloading and building the latest source was enough to get around that problem.

The next problem is that VirtualMethodInterceptor requires the target class to be public.  This is a common problem with code that builds derived classes at runtime.  Moq has the same issue, for example.  The standard workaround is to use the InternalsVisibleTo assembly attribute to give the dynamic assembly access to internal classes in the target assembly.   So after a little digging in the source I found the name of the dynamic assembly, and added this to my assembly:

[assembly: InternalsVisibleTo("Unity_ILEmit_DynamicClasses")]

Unfortunately this is not sufficient.  The Unity code has some validation that insists on the target class being public.  The code is in VirtualMethodInterceptor.cs:

public bool CanIntercept(Type t)
{
    Guard.ArgumentNotNull(t, "t");
    return t.IsClass &&
        (t.IsPublic || t.IsNestedPublic) &&
        t.IsVisible &&
        !t.IsSealed;
}

Removing the checks for IsPublic and IsVisible was enough to finally get everything to work correctly:

public bool CanIntercept(Type t)
{
    Guard.ArgumentNotNull(t, "t");
    return t.IsClass && !t.IsSealed;
}

Hopefully this will be fixed in time for the release of Unity 2.0.

Update: For internal interfaces with InterfaceInterceptor, you need this:

[assembly: InternalsVisibleTo("Unity_ILEmit_InterfaceProxies")]
Advertisement

2 comments

  1. Cheers Andy. I’ve been banging my head against this for a couple of hours now.

    BTW Unity 2.0 has been officially released and the VirtualMethodInterceptor STILL checks for the targeted type being public: http://unity.codeplex.com/SourceControl/changeset/view/50871#427102

  2. Andy says:

    I raised a bug against Unity, but it was closed with “The InternalVisibleTo approach is a hack and not supportable going forward.”

    http://unity.codeplex.com/WorkItem/View.aspx?WorkItemId=6623