Interface interception

Mar 7, 2013 at 3:19 PM
Edited Mar 7, 2013 at 3:30 PM
Hi all,

I believe I'm pushing Unity a little bit. But anyway, here is what I'd like to know if it is possible to do:

Assume I have the interface:
[InterceptAttribute]
public interface IFoo
{
    [AnotherInterceptAttribute]
    void Methodo();
}
The interceptions work just fine with any class that implements that interface and is resolved from container. Now, assume I create a new interface that implements the previous one:
public interface IBar : IFoo
{

}
When I do that, and resolve IBar, IFoo interceptors are not fired. Those attributes are guaranteeing invariant and I really need them to be fired up.

So my question is: how can I fire IFoo interceptors when resolving IBar? Is that possible? If so, how can I achieve that?

Another piece of information: I'm configure everything via code, so I need to do that via code and no xml config file.

Thanks,

Allan
Mar 7, 2013 at 5:34 PM
I don't like answering my own questions but here it goes:

I did some research and found out about InterfaceInterceptor. That interceptor has solved my problem.

Thanks,

Allan
Mar 7, 2013 at 7:12 PM
allanfagner wrote:
I don't like answering my own questions but here it goes:

I did some research and found out about InterfaceInterceptor. That interceptor has solved my problem.

Thanks,

Allan
It actually did not solve the problem. I was registering IBar (from above example) to be intercepted. So, my question still stands: how can I fire IFoo interceptors when resolving IBar? And I believe I forgot to mention I don't want to register IBar for interception, only for container resolution.
Mar 7, 2013 at 8:14 PM
Edited May 1, 2013 at 9:15 PM
You didn't post that much code so I'm filling in some blanks here and have made a few assumptions. Here is a start of a solution using a container extension.

So I'm assuming we have the following class and interfaces defined:
    [InterceptAttribute]
    public interface IFoo
    {
        [LogHandler]
        void Methodo();
    }

    public interface IBar : IFoo
    {
    }

    public class Bar : IBar
    {
        public void Methodo()
        {
            Console.WriteLine("In Methodo");
        }
    }
Now I'm treating InterceptAttribute as a marker attribute to determine if we want to intercept and I've applied a custom call handler attribute on the method Methodo
    public class InterceptAttribute : Attribute
    {
    }

    public class LogHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new LogCallHandler();
        }
    }

    public class LogCallHandler : ICallHandler
    {
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            Console.WriteLine("Invoke " + input.MethodBase.Name);
            return getNext()(input, getNext);
        }

        public int Order
        {
            get;
            set;
        }
    }
Next I defined a container extension to check all base interfaces to see if any contain the InterceptAttribute and if they do register for interception:
    public class UnityInterfaceInterceptionRegisterer : UnityContainerExtension
    {
        protected override void Initialize()
        {
            base.Container.AddNewExtension<Interception>();
            base.Context.Registering += new EventHandler<RegisterEventArgs>(this.OnRegister);
        }

        private void OnRegister(object sender, RegisterEventArgs e)
        {
            IUnityContainer container = sender as IUnityContainer;

            if (e != null && e.TypeFrom != null && e.TypeFrom.IsInterface)
            {
                // Set up interception on this interface
                if (e.TypeFrom.GetCustomAttributes(typeof(InterceptAttribute), false).Count() > 0)
                {
                    container.Configure<Interception>()
                        .SetInterceptorFor(e.TypeFrom, e.Name, new InterfaceInterceptor());
                }

                // Setup interception on all base interfaces
                foreach (var iface in e.TypeFrom.GetInterfaces())
                {
                    if (iface.GetCustomAttributes(typeof(InterceptAttribute), false).Count() > 0)
                    {
                        container.Configure<Interception>()
                            .SetInterceptorFor(e.TypeFrom, e.Name, new InterfaceInterceptor());
                    }
                }
            }
        }
    }
And finally register the interface, resolve and invoke:
    IUnityContainer container = new UnityContainer()
        .AddNewExtension<UnityInterfaceInterceptionRegisterer>();

    container.RegisterType<IBar, Bar>();

    var bar = container.Resolve<IBar>();
    bar.Methodo();
This will generate the output:
Invoke Methodo
In Methodo
If it's not the exact scenario hopefully it gives some ideas. You could also look at this similar Stack Overflow answer: http://stackoverflow.com/a/11920466/114664 .

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Mar 7, 2013 at 8:15 PM
Unity generates a proxy class that implements IFoo and tunnels all calls to that interface through the interception pipeline. It cannot generate "half a proxy" for IBar and intercept just the calls that are made to the IFoo part.

Have a look at the documentation of the various interception types for more details.
Mar 8, 2013 at 12:52 PM
Randy,

You have really nailed it down! I had just to make some minor changes to have your example working the way I needed.

Really appreciate your tips.

Thanks,

Allan