【发布时间】:2010-12-31 19:38:47
【问题描述】:
我正在使用一些与 WebForms/MVC 无关的工具,并且我需要在给定 HttpContextBase 对象的引用的情况下获取 HttpContext 的实例。我不能使用HttpContext.Current,因为我也需要它以异步方式工作(HttpContext.Current 在异步请求期间返回null)。我知道HttpContextWrapper,但走错路了。
【问题讨论】:
我正在使用一些与 WebForms/MVC 无关的工具,并且我需要在给定 HttpContextBase 对象的引用的情况下获取 HttpContext 的实例。我不能使用HttpContext.Current,因为我也需要它以异步方式工作(HttpContext.Current 在异步请求期间返回null)。我知道HttpContextWrapper,但走错路了。
【问题讨论】:
你不能。
HttpContextBase 的全部目的是抽象出对具体 HttpContext 类的依赖。虽然它可能包含一个具体的HttpContext(例如httpContextWrapper的情况),但其他实现可能与HttpContext完全无关。 p>
您最好的选择是定义一个可以为您获取HttpContextBase 的自定义抽象工厂,因为您始终可以将具体的HttpContext 包装在HttpContextWrapper 中。
【讨论】:
IHttpHandler 实现,您最终不得不在(响应包装器)中放置大量抽象来进行单元测试,这感觉不对,但最终成为唯一的选择.
你可以,
var abstractContext = new System.Web.HttpContextWrapper(System.Web.HttpContext.Current);
【讨论】:
最简单的方法是获取应用程序ApplicationInstance,并使用其Context 属性:
// httpContextBase is of type HttpContextBase
HttpContext context = httpContextBase.ApplicationInstance.Context;
(感谢Ishmael Smyrnow 在 cmets 中注意到这一点)
您可以,尤其是当您收到的HttpContextBase 实例在运行时是HttpContextWrapper 类型时。以下示例说明了如何执行此操作。它假设您有一个名为Foo 的方法,它接受上下文为HttpContextBase,但随后需要调用第三方程序集(您可能没有好运来修改)中的一个方法,该方法期望输入上下文作为HttpContext。
void Foo(HttpContextBase context)
{
var app = (HttpApplication) context.GetService(typeof(HttpApplication));
ThirdParty.Bar.Baz(app.Context);
}
// Somewhere in assembly and namespace ThirdParty,
// in a class called Bar, there is Baz expecting HttpContext:
static void Baz(HttpContext context) { /* ... */ }
HttpContextBase 有一个名为GetService 的方法,因为它支持IServiceProvider。 GetService 覆盖 HttpContextWrapper 代表包装 HttpContext 实例的 GetService 实现。 GetService 的 HttpContext 实现允许您查询常见的嫌疑人,如 HttpApplication、HttpRequest、HttpResponse 等。碰巧HttpApplication 有一个名为Context 的属性,它返回一个HttpContext 的实例。因此,通过GetService 向HttpContextBase 询问HttpApplication,然后读取返回的HttpApplication 实例的Context 属性,即可获得包装好的HttpContext 实例。
与HttpContextBase 不同,GetService 不会作为HttpContext 的公共成员出现,但这是因为HttpContext 明确实现了IServiceProvider.GetService 而HttpContextBase 没有。
请记住,Foo 不再是可测试的,因为它依赖于能够在测试期间解开底层的HttpContext,而这几乎是不可能伪造/存根的。然而,这个答案的重点是解决这个问题,“我如何从 HttpContextBase 获取 HttpContext 对象?”,字面意思。当您发现自己被夹在您不一定有权修改的组件之间时,图示的技术非常有用。
【讨论】:
context.ApplicationInstance.Context吗?
HttpContextBase 返回的所有Http*Base 变体中,不要错过了。 :P 我会更新答案。