The bare bones of Unity interceptions

The Enterprise Library 4.1 was released together with Unity 1.2 in which a whole interception mechanism was added as part of the aspect-oriented approach to coding and a merge of the policy injection ideas. This little note is just a stepping stone if you wish to play with the new interception namespace.

Interceptions through attributes on interfaces

In order to intercept things through attributes you need to define your own attributes based on the HandlerAttribute class, like this for instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class WatchAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new WatchHandler();
    }
}
public class WatchHandler : ICallHandler
{
    public int Order { get; set; }
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Debug.WriteLine(string.Format("Method '{0}' on object '{1}' was invoked.", input.MethodBase.Name, input.Target.GetType()));
        return getNext()(input, getNext);
 
    }
 
}

Nothing extraordinary here except maybe the Order property on which more below. Next, you can put this attribute either on interface members or on the members of a class. Let’s use an interface first:

1
2
3
4
5
6
7
8
9
10
11
12
public interface IAction
{
    [Watch]
    void Run();
}
public class SomeAction : IAction
{
    public void Run()
    {
        //whatever
    }
}

The interception consists of ‘something’ happening when the ‘Run’ method is called on any class implementing the IAction interface. This is quite a powerful feature; by defining an attribute and putting it on whatever interface member you can propagate some action to a wide set of classes. This gives a centralized handler across your all API, which is usually referred to as cross-cutting code in aspect-oriented terms.

Of course, in order to let things happen you need to weave it into a Unity container:

1
2
3
4
5
IUnityContainer container = new UnityContainer();
container.AddNewExtension< Interception>();
container.RegisterType< IAction, SomeAction>().Configure< Interception>().SetInterceptorFor< IAction>(new InterfaceInterceptor());
IAction action = container.Resolve< IAction>();
action.Run();

Notice the InterfaceInterceptor instance through which you tell the container to watch interceptions defined on an interface type.

On running the code you will see something like

Method ‘Run’ on object ‘DynamicModule.ns.Wrapped_IAction_7f6d32c1ea784597a6b488b524f25b0f’ was invoked.

in which you can see that some wrapping occured under the cap of Unity and a proxy was created to intercept the ‘Run’ calls.

Interceptions through attributes on virtual methods

The necessary code to intercept virtual methods is really the same as before except that now you need to use the VirtualMethodInterceptor rather than the InterfaceInterceptor:

1
container.Configure< Interception>().SetInterceptorFor< SomeAction>(new VirtualMethodInterceptor());

and instead of putting the Watch attribute on the interface you need to set it on a virtual method

1
2
3
4
5
6
7
8
public class SomeAction
{
    [Watch]
    public virtual void Run()
    {
        //whatever
    }
}

Interceptions through rules

The alternative to attribute based interceptions is to filter out the stuff you want to intercept through a rule, say like the following:

1
2
3
4
5
6
7
public class MyRule : IMatchingRule
{
    public bool Matches(MethodBase member)
    {
        return member.Name == "DoIt";
    }
}

The MethodBase gives you information on the member being part of some class and you could inject at this place some security code to check access to the member. This rule is baked into the container through the configuration of the Interception block:

1
2
3
4
5
6
7
8
9
10
11
IUnityContainer container = new UnityContainer();
container.AddNewExtension< Interception>();
container.RegisterType< MyClass>();
container.Configure<interception>()
    .AddPolicy("TheNameYouLike")
    .AddMatchingRule(new MyRule())
    .AddCallHandler(new WatchHandler());
container.Configure< Interception>().SetInterceptorFor< MyClass>(new TransparentProxyInterceptor());
MyClass c = container.Resolve< MyClass>();
c.DoIt();
</interception>

You can add multiple handlers to a rule but there is a catch here: the class you wish to intercept needs to inherit from MarshalByRefObject. While it doesn’t harm to let one of your classes inherit from it, it does represent a constraint in general.

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyClass : MarshalByRefObject
{
    public virtual void DoIt()
    {
        //whatever you like
        return;
    }
    [InjectionConstructor]
    public MyClass()
    {
 
    }
}

If you scan the inheritance list of MarshalByRefObject you’ll not see many classes you use in mainstream code and, in fact, the MarshalByRefObject seems to me more a remnant of the remoting era. So, for practical purposes this could be a problem.

Order please

The ICallHandler has an Order property which allows you to organize handler if multiple have been assigned. As an experiment, define the following handlers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class WatchHandler : ICallHandler
{
    public int Order { get; set; }
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Debug.WriteLine(string.Format("First watch: Method '{0}' on object '{1}' was invoked and caught in order {2}.", input.MethodBase.Name, input.Target.GetType(), Order));
        return getNext()(input, getNext);
 
    }
 
}
public class WatchHandler2 : ICallHandler
{
    public int Order { get; set; }
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Debug.WriteLine(string.Format("Second watch: Method '{0}' on object '{1}' was invoked  and caught in order {2}.", input.MethodBase.Name, input.Target.GetType(),Order));
        return getNext()(input, getNext);
 
    }
 
}

and assign them like this

1
2
3
4
5
6
7
WatchHandler w1 = new WatchHandler { Order = 1};
WatchHandler2 w2 = new WatchHandler2 { Order = 2};
container.Configure< Interception>()
    .AddPolicy("TheNameYouLike")
    .AddMatchingRule(new MyRule())
    .AddCallHandler(w2)
    .AddCallHandler(w1);

Now switch the last two line of code and you will notice that it doesn’t matter in which order they are put there. This is because the Order property is called to organize them and we assigned a higher rank to the second handler. Not a formidable feature but you never know.

Related Posts

G2's interface hierarchy

Some (self-indulgent) overview of G2's interface hierarchy is available.

Read more

Extensibility through Unity

This is the third part (see part I & part II) of my series on Unity & ObjectBuilder. The previous introductory material was only there to make the stuff described below more accessible and the framework described here is in fact a complete addition to the Unity toolset, it allows you:

  • to use Unity much like the Microsoft Extensibility Framework (MEF), i.e. use import/export attributes to combine instances
  • to use Unity to create action flows (workflows in fact but the term has an unintended technical conotation here)
  • to use Unity to inject at runtime other objects and sub-objects through a dotted attribute notation
Before giving you concrete code samples let me first highlight what I wanted to achieve and why I created this framework in the first place. During the development of GraphSquare (see this article and the architecture series) I needed a flexible mechanism to convert entities and to let the MVC model pass various stages of transformation to serialize things to a variety of export formats (binary, XML, WCF entities and so on). The idea can be best understood as a combination of ORM and serialization. Imagine that you have some domain entities which need to be converted to data entities through a series of actions like depicted in the picture below. Now, the 'transaction' here is a package which combines the start and end result and the 'workflow' is a series of 'actions' which can be chained and which reacts according to what the transaction state (content) is. Obviously, the transformation to an XML output requires a different set of actions than a binary one, yet there is some overlap. Each action requires either the whole domain entity or some part of it and maybe even some information from the already created data entities. In addition, writing code to assign all this to each instance becomes a repetitive task. So, the idea quickly became involved and difficult to implement. Until I realized that Unity and ObjectBuilder together with their extensibility model were perfectly adapted to this kind of paradigm.

Read more

2 Responses to The bare bones of Unity interceptions

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

top