0

This is specific to LightInject's interception. Is it possible to apply interception logic based on PerWebRequest lifetime so that interception logic can be conditionally turned on/off based on user input? E.g. something like this.

    public static void Configure()
    {
        var serviceContainer = new ServiceContainer();
        serviceContainer.EnablePerWebRequestScope();
        serviceContainer.Register<ITraceSwitcher, TraceSwitcher>(new PerScopeLifetime());
        serviceContainer.Register<IMyService, MyService>(new PerScopeLifetime());
        serviceContainer.Intercept(x => x.ServiceType == typeof(IMyService), (y, z) => DefineProxyType(z, IsTracingEnabled));

        ServiceLocator.SetLocatorProvider(() => new LightInjectServiceLocator(serviceContainer));
    }

    private static void DefineProxyType(ProxyDefinition proxyDefinition, Func<bool> isTracingEnabled)
    {
        if (isTracingEnabled())
            proxyDefinition.Implement(() => new MyServiceInterceptor(), m => m.Name == "SomeMethod");
    }

    private static bool IsTracingEnabled()
    {
        var traceSwitcher = ServiceLocator.Current.GetInstance<ITraceSwitcher>();
        return traceSwitcher.IsTracingEnabled();
    }

Now because IMyService lifetime is defined as PerWebRequest so it is created for every web request and I was under impression that it would also call Intercept method everytime it creates MyService instance so that it can dynamically decide to apply interception logic depending on whether tracing is enabled or disabled by user. However it looks like that it calls Intercept method only once for the first time when IMyService instance is requested and for all subsequent requests it reuses the same Interception mechanism.

I also know I can use ITraceSwitcher logic within MyServiceInterceptor and then decide to use or bypass interception logic there but I want to avoid creation of proxies to begin with if tracing is disabled to avoid overhead of proxy calls through reflection but this is only possible if Intercept method is called for every web request. Please let me know if it's doable or there is a better way?

Thanks,

Syed Danish.

Syed Danish
  • 106
  • 1
  • 9

1 Answers1

3

You can put the IsTracingEnabled method call directly into the predicate that decides if the services should be intercepted. The proxy type will only be created if it matches the predicate.

using LightInject;
using LightInject.Interception;

class Program
{
    static void Main(string[] args)
    {

        var container = new ServiceContainer();
        container.Register<IFoo, Foo>();
        container.Intercept(sr => sr.ServiceType == typeof(IFoo) && IsTracingEnabled(), (factory, definition) => DefineProxyType(definition));

        var foo = container.GetInstance<IFoo>();
    }

    private static void DefineProxyType(ProxyDefinition proxyDefinition)
    {            
        proxyDefinition.Implement(() => new SampleInterceptor(), m => m.Name == "SomeMethod");
    }

    private static bool IsTracingEnabled()
    {
        return true;
    }
}

public class SampleInterceptor : IInterceptor
{
    public object Invoke(IInvocationInfo invocationInfo)
    {
        return invocationInfo.Proceed();
    }
}

public interface IFoo { }

public class Foo : IFoo { }

Best regards

Bernhard Richter

seesharper
  • 3,249
  • 1
  • 19
  • 23
  • Hi Bernhard, it still doesn't address the issue mentioned in question. "Intercept" method is still called once only when first instance is retrieved from container. If you retrieve multiple instances one after another, it would still use the same interception proxy. E.g. if you do this `` – Syed Danish Aug 01 '14 at 15:24
  • `var foo = container.GetInstance(); foo = container.GetInstance(); foo = container.GetInstance();` It would call Intercept method and create proxy only for first call to Container.GetInstance(). This scenario is more relevant in web applications with PerWebRequest lifetime when a user has option to switch tracing on/off between multiple web requests in which case if tracing is off, calls should not be intercepted however they would still be intercepted if interception proxy is already created on the first web request which is what I have asked in my original question. – Syed Danish Aug 01 '14 at 15:33
  • In this case it would probably be best to always invoke the interceptor and put the IsTracingEnabled logic inside the interceptor itself. The cost of calling through a proxy is hardly going to affect the overall performance of your application. The proxy is simply a "generic" decorator and calls to the proxy gets compiled into IL the first time the service is requested. – seesharper Aug 03 '14 at 13:00
  • Hi Bernhard, thanks. Can you please explain what does it mean by **The proxy is simply a "generic" decorator and calls to the proxy gets compiled into IL the first time the service is requested.** Also just out of curiosity, would it be a good idea to invoke interceptor's Intercept method based on corresponding intercepted type's lifetime or it would be just too much effort for little benefit? – Syed Danish Aug 07 '14 at 19:29
  • Accepted answer as this seems to be the right strategy at the moment. – Syed Danish Oct 29 '15 at 16:03