Mixin’ up Ninject, Castle Dynamic Proxy and WCF – Part III

The previous post of this series was all about the internals of a binding syntax for Ninject that enables binding to Castle dynamic proxies. At the end I suggested using that syntax to create dynamic WCF client proxies.

kernel.Bind<IEchoService>()
	.ToDynamicProxy(p => p
             .AsWcfProxy()
             .UsingInterceptor<LogInterceptor>())
        .InSingletonScope();
// ...
var proxy = kernel.Get<IEchoService>();
Console.WriteLine(proxy.Echo("Hey there"));

The previous code creates a dynamic proxy with a logging interceptor that ends up invoking a WCF service whose contract is represented by the IEchoService interface. This may look a bit esoteric, but the principles are quite simple:

  • It is assumed that there is a single client endpoint configuration for IEchoService on Web.config. This is reasonable for most scenarios but the code could be enhanced so that the endpoint configuration or configuration name would be a parameter of the AsWcfProxy method. But let’s keep it simple.
  • The proxy can be used without worrying about disposal and the same instance can be used multiple times. This means that the dynamic proxy is actually working as an “implicit factory”, which can be more convenient to use.
  • I’m avoiding using service references generated by svcutil. This means that we don’t have a generated “EchoServiceClient” class to be the actual target of the dynamic proxy. We’ll go with ChannelFactory instead, generating proxies on-the-fly. The code could be easily extended to also support existing WCF proxies (I’ll point that out on the appropriate time or maybe I’ll include it with the code at the end of the series).

So, first things first. We don’t have a target for the dynamic proxy, so we’ll create one when needed. That leaves us with one option: using a dynamic proxy without target. The “target” will be a WCF proxy created through ChannelFactory. But when should this proxy be created? Since I don’t want to be worried about disposal when using the dynamic proxy, a possible approach is to create a new WCF proxy before each service request and dispose it afterwards. This behavior is a perfect match for an interceptor!

class WcfProxyWithDisposalInterceptor<TInterface> : IInterceptor
{
    // Per-type cache of channel factories.
    private static ChannelFactory<TInterface> ServiceFactory = new ChannelFactory<TInterface>("*");

    void IInterceptor.Intercept(IInvocation invocation)
    {
        using (var channel = (IDisposable)ServiceFactory.CreateChannel())
        {
            invocation.ReturnValue = invocation.Method.Invoke(channel, invocation.Arguments);
        }
    }
}

The code is slightly abbreviated for clarity, but the essence is there. We have a ChannelFactory for a given service contract that is used to create a proxy on which the actual operation is invoked. Since invocation.Proceed() isn’t invoked, the interceptor will return to the caller with the return value obtained from the WCF proxy. With this interceptor in place, defining the AsWcfProxy method presented on the beginning of this post is straightforward. Of course we’ll take advantage of the binding syntax that was previously developed!

public static IBindingToProxyWithInterceptorSyntax<T> AsWcfProxy<T>(this IBindingToProxySyntax<T> binding)
 {
       return binding.WithoutTarget<WcfProxyWithDisposalInterceptor<T>>();
 }

As described before, we configure a dynamic proxy without target, whose final interceptor is the one just defined, that in turn forwards the call to the WCF service. Over the result of this method one can configure additional interceptors, since the syntax is exactly the same from the previous post. If you just want to take advantage of the “auto disposal” you can go further and define an extension method over Ninject’s syntax so that you can write:

 kernel.Bind<IEchoService>().ToWcfProxy();

At this point I’ve met the initial goal for this series of posts but… I’ve also been using Ninject’s WCF extensions to have WCF services activated using dependency injection and I figured that we could push it a little further and also enable interceptors on the service side. Yes, I know about WCF’s message inspectors, but dynamic proxies and interceptors will be at an higher level on the “service call stack”. In addition, interceptors can easily rely on dependency injection to have access to more application specific stuff, which can be harder using behaviors and message inspectors.

So.. the next (and last) post of the series will be about tweaking Ninject’s WCF extensions and using dynamic proxies on service activation.

Advertisement

Mixin’ up Ninject, Castle Dynamic Proxy and WCF – Part II

On the previous post of this series I introduced an extension to Ninject’s binding syntax  that allows you to define bindings to Castle dynamic proxies by writing something like:

kernel.Bind<IService>().ToDynamicProxy(p => p
         .WithTarget<ServiceImpl>()
         .UsingInterceptor<ConsoleLogInterceptor>());

Before going into the details of the syntax it’s worthy pointing out the base ideas:

  • Both proxies with and without target should be supported;
  • Proxies without target need at least one interceptor and this interceptor must not make the invocation proceed;
  • Proxies with target also need at least one interceptor (why using a dynamic proxy with target and no interceptors?) but there’s no special semantic like in the previous case;
  • An arbitrary number of interceptors can be added to the dynamic proxy
  • For proxies with target, target types should be resolved using Ninject;
  • Interceptors should also be resolved using Ninject;
  • Targets and interceptors may also be specified by instance or using a Func<IContext, T>, to keep the syntax flexible and similar to Ninject’s

The ToDynamicProxy method is an extension method to Ninject’s IBindingToSyntax and receives a lambda that defines the dynamic proxy configuration. Since the two options of proxies are with or without target, the following type is used for the lambda parameter:

    public interface IBindingToProxySyntax<T>
    {
	... WithTarget<TTarget>() where TTarget : T;
	... WithTarget<TTarget>(TTarget target) where TTarget : T;
	... WithTarget(Func<IContext, T> targetFactory);

	... WithoutTarget<TInterceptor>() where TInterceptor : IInterceptor;
	... WithoutTarget(IInterceptor interceptor);
	... WithoutTarget(Func<IContext, IInterceptor> interceptorFactory);
    }

I’ll get to the return types shortly. WithoutTarget receives the “final” interceptor (the one that must not proceed) by type, instance or factory. On the other hand the WithTarget method receives the proxy target. Note that the type argument on the interface above matches the one on ToDynamicProxy, which in turn matches the one on Ninject’s syntax.

IBindingWhenInNamedWithOrOnSyntax<T> ToDynamicProxy<T>(
            this IBindingToSyntax<T> binding,
            Func<IBindingToProxySyntax<T>, ...> dynamicProxyConfig)

The Func could be void but this would allow incorrect configurations. The approach in place is to use a return type that can only be obtained when defining correct configurations. You write exactly the same code but you get “compile time correctness”. But what exactly is a correct configuration for the dynamic proxy? If the WithoutTarget method above is used, then we’re good to go because the needed interceptor is configured. But when using WithTarget, we still need an interceptor. It is not specified directly on this method because the generic version would need both TTarget and TInterceptor type arguments to be specified. And that’s not so neat. So, WithTarget and WithoutTarget have different return types:

public interface IBindingToProxyWithInterceptorSyntaxBase<T>
{
	IBindingToProxyWithInterceptorSyntax<T> UsingInterceptor<TInterceptor>() where TInterceptor : IInterceptor;
	IBindingToProxyWithInterceptorSyntax<T> UsingInterceptor(IInterceptor interceptor);
	IBindingToProxyWithInterceptorSyntax<T> UsingInterceptor(Func<IContext, IInterceptor> interceptorFactory);
}

// Returned by WithTarget
public interface IBindingToProxyWithTargetAndWithInterceptorSyntax<T> : IBindingToProxyWithInterceptorSyntaxBase<T> { }
// Returned by WithoutTarget
public interface IBindingToProxyWithInterceptorSyntax<T> : IBindingToProxyWithInterceptorSyntaxBase<T> { }

The trick is the definition of the proxy configuration Func (now complete):

Func<IBindingToProxySyntax<T>, IBindingToProxyWithInterceptorSyntax<T>> dynamicProxyConfig

To get the appropriate return type – and thus the correct configuration – one needs to either:

  • Invoke WithoutTarget and optionally invoke UsingInterceptor to add more interceptors; OR
  • Invoke WithTarget and then invoke UsingInterceptor at least once.

The whole work being done behind the scenes is based on a simple principle: since we want Ninject to resolve targets and interceptors we keep track of them using factories that will have access to the Ninject kernel. Therefore the implementation of the syntax interfaces presented above is backed on a set of factories for the interceptors and a factory for the dynamic proxy itself:

private List<Func<IContext, IInterceptor>> _interceptorFactories;
private Func<IContext, IInterceptor[], T> _proxyFactory;

Note that IContext is an Ninject interface and provides access to the kernel in use on the current activation request. The implementation then has a method to actually create the dynamic proxy:

public T CreateProxy(IContext ctx)
{
	var interceptors = _interceptorFactories
		.Select(f => f(ctx))
		.ToArray();
	return _proxyFactory(ctx, interceptors);
}

The actual interceptor factories depend on which UsingInterceptor overloads were used. For instance, the generic overload registers a factory that requests the interceptor to the kernel. The proxy factory, in turn, depends on whether WithTarget or WithoutTarget was used. For instance:

public ... WithTarget<TTarget>() where TTarget : T
{
	_proxyFactory = (ctx, interceptors) => 
               ProxyGenerator.CreateInterfaceProxyWithTarget<T>(
                    ctx.Kernel.Get<TTarget>(),
                    interceptors);
	return this;
}

After this, implementing the ToDynamicProxy – which actually does the binding – comes down to defining an Ninject binding using the CreateProxy method above.

public static ... ToDynamicProxy<T>(
       this IBindingToSyntax<T> binding,
       Func<IBindingToProxySyntax<T>, IBindingToProxyWithInterceptorSyntax<T>> dynamicProxyConfig)
{
        var proxyBinding = new BindingToProxySyntax<T>();
	dynamicProxyConfig(proxyBinding);
	return binding.ToMethod(proxyBinding.CreateProxy);
}

Pretty cool right? But this series of posts is also about WCF.. so what about creating dynamic WCF proxies?

kernel.Bind<IEchoService>()
	.ToDynamicProxy(p => p
             .AsWcfProxy()
             .UsingInterceptor<LogInterceptor>())
        .InSingletonScope();
// ...
var proxy = kernel.Get<IEchoService>();
Console.WriteLine(proxy.Echo("Hey there"));

Stay tuned for the next post!

Note: I’ll make the source code available at the end of the series

Mixin’ up Ninject, Castle Dynamic Proxy and WCF – Part I

They don’t need introduction: Ninject and Castle dynamic proxies are a must on many projects, as they help you design flexible and loosely-coupled software. If you mix them up you can get some neat stuff! On this series of (probably) 4 (small) posts I’ll present some code that enables Ninject bindings to dynamic proxies and then I’ll apply it to WCF service proxies and stubs.

To get started let’s say we have the following superb interface and implementing class:

        public interface IService
        {
            void Do();
        }

        class ServiceImpl : IService
        {
            public ServiceImpl(/* Dependencies here */) { }
            public void Do(){ ... }
        }

Using Ninject, binding IService to ServiceImpl is straightforward:

         var kernel = new StandardKernel();
         kernel.Bind<IService>().To<ServiceImpl>();

Whenever IService is requested Ninject will create an instance use ServiceImpl resolving its dependencies on the way. Now let’s say we’d like to log invocation of methods on ServiceImpl (we could go for caching, parameter validation or anything else, but for simplicity I’ll stick to an awesome console logger). A possible approach is to use Castle and create a dynamic proxy with an interceptor that logs method calls. Castle has two major types of proxies: with and without target. On this case, we need a proxy with target, since we want the call to actually reach ServiceImpl (the proxy target). To use the proxy whenever an instance of IService is needed the previous Ninject binding has to be enhanced as follows:

 var proxyGenerator = new ProxyGenerator();
 kernel.Bind<IService>()
    .ToMethod(ctx => proxyGenerator.CreateInterfaceProxyWithTarget(
        ctx.Kernel.Get<ServiceImpl>(),
        new ConsoleLogInterceptor()));

The proxy creation needs to be delayed because we still want the instances of ServiceImpl to be created by Ninject, hence the use of ToMethod (note that the interceptor could also be requested to the Ninject kernel). This code works but quickly becomes very verbose. What if one has multiple interceptors that should be resolved through the kernel? What if we want to bind another interface to a dynamic proxy in a similar way? When using Ninject and Castle at our current project, me and my colleague Antoine Aubry came up with some extensions to Ninject’s syntax that after some turns and tweaks allow you to rewrite the previous binding like this:

   kernel.Bind<IService>().ToDynamicProxy(p => p
         .WithTarget<ServiceImpl>()
         .UsingInterceptor<ConsoleLogInterceptor>());

On the next post I’ll cover some details on the implementation of those extensions.