通过使用构造函数注入 HttpModule 来注入 HttpContext 是否错误?

Is Injecting HttpContext by using constructor injection into HttpModule wrong?

我有一个自定义的 HttpModule,我在其中跟踪 http 请求,部分实现如下;

    private readonly HttpContextBase _httpContext;
    private readonly ISessionContext _sessionContext;

    public ASHttpModule(HttpContextBase httpContext,
        ISessionContext sessionContext)
    {
        this._httpContext = httpContext;
        this._sessionContext = sessionContext;
    }
    public void Init(HttpApplication context)
    {
        context.BeginRequest += Context_BeginRequest;
        context.EndRequest += Context_EndRequest;
    }
    private void Context_BeginRequest(object sender, EventArgs e)
    {
       Stopwatch stopwatch = new Stopwatch();
       _httpContext.Items["Stopwatch"] = stopwatch;
       stopwatch.Start();
    }
    private void Context_EndRequest(object sender, EventArgs e)
    {
            Stopwatch stopwatch = (Stopwatch)_httpContext.Items["Stopwatch"];
            if (stopwatch == null)
                return;

            stopwatch.Stop();
            TimeSpan ts = stopwatch.Elapsed;
            //Check current httprequest variables and log if have to

    }

这里是我的依赖注册(使用Autofac);

        builder.RegisterType<WebSessionContext>()
            .As<ISessionContext>().InstancePerRequest();
        builder.Register(c => (new HttpContextWrapper(HttpContext.Current) as HttpContextBase))
            .As<HttpContextBase>()
            .InstancePerRequest();
        builder.Register(c => c.Resolve<HttpContextBase>().Request)
            .As<HttpRequestBase>()
            .InstancePerRequest();
        builder.Register(c => c.Resolve<HttpContextBase>().Server)
            .As<HttpServerUtilityBase>()
            .InstancePerRequest();
        builder.Register(c => c.Resolve<HttpContextBase>().Session)
            .As<HttpSessionStateBase>()
            .InstancePerRequest();

这里的问题是 HttpModule 只构造一次,而 HttpContext 需要为每个请求注入。我找到的解决方案是将 DependencyResolver 用作 ;

      HttpContextBase _httpContext = DependencyResolver.Current.GetService<HttpContextBase>();

但是,我想避免这种用法,因为 ServiceLocator 被认为是反模式。

有没有不使用 DependencyResolver 将 HttpContext 注入 HttpModule 的解决方案?

您可以尝试使用工厂来获取正确的 HttpContext 实例:

private readonly Func<HttpContextBase> _httpContextFactory;
private readonly ISessionContext _sessionContext;

public ASHttpModule(Func<HttpContextBase> httpContextFactory,
    ISessionContext sessionContext)
{
    this._httpContextFactory = httpContextFactory;
    this._sessionContext = sessionContext;
}
private void Context_BeginRequest(object sender, EventArgs e)
{
   var httpContext = this._httpContextFactory();
   Stopwatch stopwatch = new Stopwatch();
   httpContext.Items["Stopwatch"] = stopwatch;
   stopwatch.Start();
}

我假设 Autofac 也可以注入 Func`1 个实例。如果没有,您可能需要创建一个简单的 class 作为 HttpContext 的工厂。

然后可以注入:

  • 正常运行→() => HttpContextWrapper(HttpContext.Current)
  • 当testing/mocking→() => new HttpContextMock()