【问题标题】:LightInject PerWebRequest InterceptionLightInject PerWebRequest 拦截
【发布时间】:2014-07-31 15:49:08
【问题描述】:

这是特定于 LightInject 的拦截。是否可以基于 PerWebRequest 生命周期应用拦截逻辑,以便可以根据用户输入有条件地打开/关闭拦截逻辑?例如。像这样的。

    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();
    }

现在因为 IMyService 生命周期被定义为 PerWebRequest 所以它是为每个 Web 请求创建的,我的印象是它每次创建 MyService 实例时也会调用 Intercept 方法,以便它可以根据是否跟踪动态决定应用拦截逻辑由用户启用或禁用。但是看起来它在第一次请求 IMyService 实例时只调用一次 Intercept 方法,并且对于所有后续请求,它重用相同的拦截机制。

我也知道我可以在 MyServiceInterceptor 中使用 ITraceSwitcher 逻辑,然后决定在那里使用或绕过拦截逻辑,但我想避免在禁用跟踪时创建代理,以避免通过反射产生代理调用的开销,但这只是如果为每个 Web 请求调用 Intercept 方法,则可能。请让我知道它是否可行或有更好的方法?

谢谢,

赛德丹麦语。

【问题讨论】:

    标签: dependency-injection aop interception perwebrequest light-inject


    【解决方案1】:

    您可以将 IsTracingEnabled 方法调用直接放入决定是否应拦截服务的谓词中。只有与谓词匹配时才会创建代理类型。

    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 { }
    

    最好的问候

    伯恩哈德·里希特

    【讨论】:

    • 您好 Bernhard,它仍然没有解决所提到的问题。仅当从容器中检索到第一个实例时,仍会调用一次“拦截”方法。如果您一个接一个地检索多个实例,它仍然会使用相同的拦截代理。例如。如果你这样做 ``
    • var foo = container.GetInstance&lt;IFoo&gt;(); foo = container.GetInstance&lt;IFoo&gt;(); foo = container.GetInstance&lt;IFoo&gt;(); 它将调用 Intercept 方法并仅为第一次调用 Container.GetInstance() 创建代理。当用户可以选择在多个 Web 请求之间打开/关闭跟踪时,这种情况在具有 PerWebRequest 生命周期的 Web 应用程序中更为相关,在这种情况下,如果跟踪关闭,则不应拦截调用,但如果拦截代理已经存在,它们仍将被拦截在我最初的问题中提出的第一个网络请求中创建。
    • 在这种情况下,最好总是调用拦截器并将 IsTracingEnabled 逻辑放入拦截器本身。通过代理调用的成本几乎不会影响应用程序的整体性能。代理只是一个“通用”装饰器,对代理的调用在第一次请求服务时被编译到 IL 中。
    • 您好,伯恩哈德,谢谢。您能否解释一下代理只是一个“通用”装饰器的含义,并且对代理的调用在第一次请求服务时被编译到 IL 中。 也只是出于好奇,会不会根据相应拦截类型的生命周期调用拦截器的 Intercept 方法是个好主意,否则会付出太多努力而没有什么好处?
    • 已接受答案,因为目前这似乎是正确的策略。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2013-06-25
    • 2018-08-09
    • 2014-03-10
    • 2023-03-13
    相关资源
    最近更新 更多