Interception Using StructureMap 3.*
D

2

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.

Diversified answered 11/5, 2014 at 14:38 Comment(0)
D
7

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 :)

Diversified answered 13/5, 2014 at 21:59 Comment(0)
U
1

I find the best place to go for any new versions is directly to the source.

If it's written well, then it will include test cases. Thankfully structuremap does include test cases.

You can explore the tests here

In the meantime I've written an example of an Activator Interceptor, and how to configure it.

static void Main()
{
    ObjectFactory.Configure(x =>
    {
        x.For<Form>().Use<Form1>()
            .InterceptWith(new ActivatorInterceptor<Form1>(y =>  Form1Interceptor(y), "Test"));
    });
    Application.Run(ObjectFactory.GetInstance<Form>());

}

public static void Form1Interceptor(Form f)
{
    //Sets the title of the form window to "Testing"
    f.Text = "Testing";
}

EDIT:

How to use a "global" filter using PoliciesExpression

[STAThread]
static void Main()
{
    ObjectFactory.Configure(x =>
    {
        x.Policies.Interceptors(new InterceptorPolicy<Form>(new FuncInterceptor<Form>(y => Intercept(y))));
    });
    Application.Run(ObjectFactory.GetInstance<Form>());
}

private static Form Intercept(Form form)
{
    //Do the interception here
    form.Text = "Testing";
    return form;
}
Underprivileged answered 11/5, 2014 at 22:58 Comment(7)
Thank you very much. But what I'm looking for is an approach that would allow me to intercept method calls using Castle Dynamic Proxy. And also I'd like to use it for several interfaces all together, e.g. for all services within given assembly. Right now I'm using my own convention scanner and would like to add interception logic into that. something like this: registry.For(pluginType).Singleton().Use(type).Intercept(.... and so onDiversified
Post your old working code with SM2, and maybe then I can help further.Underprivileged
Basicly I did it in SM2 by calling ConfigurationExpression.RegisterInterceptor method, that required simple TypeInterceptor instance.After many hours of struggling I discovered that what I want is something similar to FuncInterceptor that would work fine if I just wanted to do interception for one particular plugin typeDiversified
i.e. instead of something like this: registry.For<IPluginType>() .Use<PluggedInType>() .InterceptWith(new FuncInterceptor<IPluginType>(blablabla)); I want to do the same thing inside DefaultConventionScanner, i.e. dynamically, without knowing the exact typeDiversified
I see this means to write some custom implementation of the new IInterceptor, that would do the trick inside ToExpression overload. But I'm not yet well familiar with concept of expressions and have to struggle a lot. Couldn't they just add simple Intercept method that would just require a simple lambda expression to tweak the plugged in instance? duh...Diversified
I've edited my answer to show how to use PoliciesExpression to register a "global" interceptor. Again, if you want more detailed help, I'd suggest you update your question with the code you had for SM2, rather than writing large comments.Underprivileged
Xenolighting, after three days of war, I finally solved the problem :) Below is the code snippet. Thanks for your time and attention. Cheers!Diversified

© 2022 - 2024 — McMap. All rights reserved.