InterfaceInterception not intercepting methods from derived interfaces

Apr 9, 2010 at 12:18 PM

Hi,

I've noticed that the InterfaceInterceptor doesn't intercept methods from derived interfaces. Is this by design?

I have a sample that illustrates this:

public interface IMyBaseInterface
{
	string WillNotBeIntercepted();
}

public interface IMyInterface : IMyBaseInterface
{
	string WillBeIntercepted();
}

public class MyService : IMyInterface
{
	public string WillNotBeIntercepted()
	{
		return "Test 1";
	}

	public string WillBeIntercepted()
	{
		return "Test 2";
	}
}

class Program
{
	static void Main(string[] args)
	{
		IUnityContainer container = new UnityContainer();
		container.AddNewExtension<Interception>();
		container.RegisterType<IMyInterface, MyService>(new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<PolicyInjectionBehavior>());
		
		container.Configure<Interception>().AddPolicy("MyPolicy").AddMatchingRule(new MemberNameMatchingRule("*")).AddCallHandler(new TestCallHandler());

		var service = container.Resolve<IMyInterface>();

		Console.WriteLine(service.WillNotBeIntercepted());
		Console.WriteLine(service.WillBeIntercepted());
		
		Console.Read();
	}
}
public class TestCallHandler : ICallHandler
{
	public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
	{
		Console.WriteLine("Invoked {0}", input.MethodBase.Name);

		IMethodReturn ret = getNext().Invoke(input, getNext);
		
		return ret;
	}

	public int Order { get; set; }
}
This will result in the following output:
Test 1 
Invoked WillBeIntercepted
Test 2
Regards,
Anders Ljusberg
Apr 12, 2010 at 4:22 AM

I'm not sure if it is by design but I do recall that there was an error for this same scenario just by calling Resolve.  Here is the logged issue -http://unity.codeplex.com/WorkItem/View.aspx?WorkItemId=3685.  It was closed and fixed but no detail if the fix was supposed to intercept the methods from the base interface  as well.  There was a link to a solution that does the full interception but it uses the Unity assemblies version 1.2.

 

Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 12, 2010 at 9:19 AM

I was able to do a similar workaround by creating my own InterfaceInterceptor. It's a copy of the standard interceptor except for this method:

private IEnumerable<MethodImplementationInfo> DoGetInterceptableMethods(
	Type interceptedType,
	Type implementationType)
{
	if(interceptedType.IsInterface && implementationType.IsInterface
		&& interceptedType.IsAssignableFrom(implementationType))
	{
		var methods = interceptedType.GetMethods();
		for(int i = 0; i < methods.Length; ++i)
		{
			yield return new MethodImplementationInfo(methods[i], methods[i]);
		}
	}
	else
	{
		InterfaceMapping mapping = implementationType.GetInterfaceMap(interceptedType);
		for(int i = 0; i < mapping.InterfaceMethods.Length; ++i)
		{
			yield return new MethodImplementationInfo(mapping.InterfaceMethods[i], mapping.TargetMethods[i]);
		}
		foreach(var baseInterface in interceptedType.GetInterfaces())
		{
			mapping = implementationType.GetInterfaceMap(baseInterface);
			for(int i = 0; i < mapping.InterfaceMethods.Length; ++i)
			{
				yield return new MethodImplementationInfo(mapping.InterfaceMethods[i], mapping.TargetMethods[i]);
			}
		}
	}
}

Apr 13, 2010 at 5:05 AM

I should've revisited the docs earlier.  Yes, I do think it's by design as it was mentioned in the disadvantages of the InterfaceInterceptor that it only intercepts methods on a single interface.

 

Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com