Castle Dynamic Proxy tutorial part VIII: Interface proxy without target

This is part eight of my tutorial on Castle Dynamic Proxy.

After a short break let’s get right back to our Dynamic Proxy work.

Last time I introduced different kinds of proxies you can create with Castle Dynamic Proxy. Today, we’ll talk about interface proxy without target. As you probably know, interface by itself can not exist. It’s a contract defining what its implementer can do. As such you do need an implementer. If you create an interface proxy without target however you don’t need to provide the implementer. Dynamic Proxy creates it for you. This is pretty powerful.

There are times where you don’t want to create a new class to implement the interface, for variety of reasons. One such case might be using API that requires an interface, where a delegate would be more appropriate. Back in .NET 1.0, 1.1 times having methods accepting delegates was considered a code smell. This is understandable, if you remember that we didn’t have lambdas, anonymous delegates, or even generics back then.

Now however, it’s often more convenient to pass a lambda instead of creating manually a type. If you’re working with API that accepts interface, wishing you could pass a delegate inside, I have a good news for you – interface proxy without target may help you.

Let’s consider a simple interface:

public interface IAnsweringEngine
{
	int GetAnswer( string s );
}

and some public API that consumes it:

public interface IDeepThought
{
	void SetAnsweringEngine(IAnsweringEngine answeringEngine);
} 

Now, considering your answering engine is very simple one-liner, you might wish to not create a new class in code, but rather pass a lambda in. This however will not work.

IDeepThought d = GetSuperComputer();
d.SetAnsweringEngine( ( string s ) => s.Length ); 

With what we learned however so far we can make it work. All we need to do, is to build a proxy for that interface, with our delegate providing the implementation. See the following test:

[Fact]
public void Should_be_able_to_wrap_interface_with_one_method()
{
	Func<string, int> length = s => s.Length;
	var wrapped = DelegateWrapper.WrapAs<IAnsweringEngine>( length );
	Assert.NotNull( wrapped );
	var i = wrapped.GetAnswer( "Answer to Life the Universe and Everything" );
	Assert.Equal( 42, i );
} 

Notice we don’t have any manually created implementer of IAnsweringEngine here. So how does it work?

When implementing our DelegateWrapper we need to remember one thing about interface proxies without target. They are just a shells for us to fill. Dynamic Proxy does create a class that implements the interface, but it does not know what logic to put into it.

As such it is our responsibility to provide that logic and fill the shell via interceptors.

Our interceptors don’t have to be complicated. They just get a delegate and when invoked, call the delegate.

internal class MethodInterceptor : IInterceptor
{
	private readonly Delegate _impl; 

	public MethodInterceptor( Delegate @delegate )
	{
		this._impl = @delegate;
	} 

	public void Intercept( IInvocation invocation )
	{
		var result = this._impl.DynamicInvoke( invocation.Arguments );
		invocation.ReturnValue = result;
	}
}

As you can see the interceptor implementation is trivial. We could make it faster, but its not the goal of this tutorial.

Notice also that we do not call invocation.Proceed(). Since there’s no real implementation to proceed to, this would be illegal.

If we did this we would get a NotImplementedException with the following message: “This is a DynamicProxy2 error: the interceptor attempted to ‘Proceed’ for a method without a target, for example, an interface method or an abstract method“.

Keep in mind that interceptors create a pipeline (see the picture in the 2nd part of the tutorial). As such only the last interceptor must not call Proceed, all others should.

Now we can move, and implement DelegateWrapper. It’s as trivial as MethodInterceptor.

public class DelegateWrapper
{
	public static T WrapAs<T>(Delegate impl) where T : class
	{
		var generator = new ProxyGenerator();
		var proxy = generator.CreateInterfaceProxyWithoutTarget( typeof( T ), new MethodInterceptor( impl ) );
		return (T) proxy;
	}
}

That’s all, roughly a dozen lines of meaningful code to make the test pass. If you’re scratching your head wondering why I put where T : class generic constraint, it’s because class in this context actually means ‘reference type’. This may not be the best example in the world, but hopefully by now you see the potential capabilities interface proxies without target give you.

Just for kicks, we might want to extend the DelegateWrapper to handle interfaces with more than one method. Let’s write a test for that.

[Fact]
public void Should_be_able_to_write_interface_with_two_methods()
{
	Func<string, string, bool> compare = ( s1, s2 ) => s1.Length.Equals( s2.Length );
	Func<string, int> getHashCode = s => s.Length.GetHashCode();
	var comparer = DelegateWrapper.WrapAs<IEqualityComparer<string>>( compare, getHashCode );
	var stringByLength = new Dictionary<string, string>( comparer )
	{
		{ "four", "some string" },
		{ "five!", "some other string" }
	};
	Assert.Equal( 2, stringByLength.Count );
	var atFive = stringByLength["12345"];
	Assert.Equal( "some other string", atFive );
}  

We now need some way of deciding which delegate should be bound to which method. InterceptorSelector to the rescue!

public static TInterface WrapAs<TInterface>(Delegate d1, Delegate d2)
{
	var generator = new ProxyGenerator();
	var options = new ProxyGenerationOptions { Selector = new DelegateSelector() };
	var proxy = generator.CreateInterfaceProxyWithoutTarget(
		typeof( TInterface ),
		new Type[0],
		options,
		new MethodInterceptor( d1 ),
		new MethodInterceptor( d2 ) );
	return (TInterface) proxy;
}

Here’s one very simple implementation of such selector:

internal class DelegateSelector : IInterceptorSelector
{
  public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
  {
	  foreach (var interceptor in interceptors)
	  {
		  var methodInterceptor = interceptor as MethodInterceptor;
		  if (methodInterceptor == null)
			  continue;
		  var d = methodInterceptor.Delegate;
		  if (IsEquivalent(d, method))
			  return new[] { interceptor };
	  }
	  throw new ArgumentException();
  } 

  private static bool IsEquivalent(Delegate d, MethodInfo method)
  {
	  var dm = d.Method;
	  if (!method.ReturnType.IsAssignableFrom(dm.ReturnType))
		  return false;
	  var parameters = method.GetParameters();
	  var dp = dm.GetParameters();
	  if (parameters.Length != dp.Length)
		  return false;
	  for (int i = 0; i < parameters.Length; i++)
	  {
		  //BUG: does not take into account modifiers (like out, ref...)
		  if (!parameters[i].ParameterType.IsAssignableFrom(dp[i].ParameterType))
			  return false;
	  }
	  return true;
  }
} 

Notice that I also extended MethodInterceptor class to expose its delegate as a property.

On a side note, if you still don’t see how powerful interface proxies without target are, think about WCF proxies – that is exactly what they are.

Technorati Tags: , ,

Comments

arnaud says:

hey Krzysztof,
i was looking for info about VS2008 and i found your blog, i m not good at code but it seems you know very well your stuff and like it!
if i can help you with french translation do not hesitate i may help (well, i m french)
Also, are you actually fully busy or still interesting in side project opportunities? I summarize it: i spent last years at Orange as a projet manager then quit last October for a real estate website project for eastern europe, we’ve (I and the friends i work with on it) every required skills so far but lack a really skilled coder. I m going to see friends in krakow (tam studiowalem) in may, if you re just curious maybe we can share some piwo and i ll tell you few words about it?
let me know, i ll be glad!
Arnaud

Michael Harrington says:

It’s interesting that you suggest DP as a solution to have an API that expects an interface where you would prefer using a delegate, because DP itself is an API that expects an interface where I would prefer using a delegate. 😛

I’m considering simplifying a system I’m working on by using DP, but the problem is that it is performance-sensitive. I’m concerned about the overhead of the interceptor chain.

Rather than DP injecting its hooks into the the proxy and funneling the data back and forth, I’d like to just give DP a dictionary of strings to delegates to use as the implementation and skip DP’s interceptor chain altogether. Then, in theory, the only added cost to a call on a proxy would be one level of indirection.

Is there a technical reason this couldn’t be done? Is there a reason this could be a bad idea?

@Michael

So you want to do the following:
given an interface with some methods, and dictionary that maps names of these methods to delegates providing implementation create a proxy for that interface that uses the delegates as implementation. Is that correct?

I would suggest doing it the way I shown in the post, and see if the DynamicInvoke on the delegate has satisfying performance. The DP itself with single interceptor adds really very minor overhead so I wouldn’t worry about that.

If you find the performance unacceptable you will have to extend the DP itself to bind directly to delegates in a strongly typed manner. You will need DP 2.2 beta for that. However I would strongly suggest doing it the simpler way first.