Search code examples
dependency-injectioninversion-of-controlioc-containerinterceptionstructuremap3

Interception Using StructureMap 3.*


I've done interception using Castle.DynamicProxy and StructureMap 2.6 API but now can't do it using StructureMap 3.0. Could anyone help me find updated documentation or even demo? Everything that I've found seems to be about old versions. e.g. StructureMap.Interceptors.TypeInterceptor interface etc.


Solution

  • HAHAA! I f***in did it! Here's how:

    public class ServiceSingletonConvention : DefaultConventionScanner
    {
        public override void Process(Type type, Registry registry)
        {
            base.Process(type, registry);
    
            if (type.IsInterface || !type.Name.ToLower().EndsWith("service")) return;
    
            var pluginType = FindPluginType(type);
    
            var delegateType = typeof(Func<,>).MakeGenericType(pluginType, pluginType);
    
            // Create FuncInterceptor class with generic argument +
            var d1 = typeof(FuncInterceptor<>);
    
            Type[] typeArgs = { pluginType };
    
            var interceptorType = d1.MakeGenericType(typeArgs);
            // -
    
            // Create lambda expression for passing it to the FuncInterceptor constructor +
            var arg = Expression.Parameter(pluginType, "x");
    
            var method = GetType().GetMethod("GetProxy").MakeGenericMethod(pluginType);
    
            // Crate method calling expression
            var methodCall = Expression.Call(method, arg);
    
            // Create the lambda expression
            var lambda = Expression.Lambda(delegateType, methodCall, arg);
            // -
    
            // Create instance of the FuncInterceptor
            var interceptor = Activator.CreateInstance(interceptorType, lambda, "");
    
            registry.For(pluginType).Singleton().Use(type).InterceptWith(interceptor as IInterceptor);
        }
    
        public static T GetProxy<T>(object service)
        {
            var proxyGeneration = new ProxyGenerator();
    
            var result = proxyGeneration.CreateInterfaceProxyWithTarget(
               typeof(T),
               service,
               (Castle.DynamicProxy.IInterceptor)(new MyInterceptor())
               );
    
            return (T)result;
        }
    }
    

    The problem here was that SM 3.* allows interception for known types, i.e. doing something like this:

    expression.For<IService>().Use<Service>().InterceptWith(new FuncInterceptor<IService>(service => GetProxyFrom(service)));
    

    But what if you'd like to include the interception logic inside your custom scanning convention where you want to intercept all instances of type with specific signature (types having name ending on 'service', in my case)?

    That's what I've accomplished using Expression API and reflection.

    Also, I'm using here Castle.DinamicProxy for creating proxy objects for my services.

    Hope someone else will find this helpful :)