我的ASP.NET应用程序中有以下程序集:
网站 - 这是一个ASP.NET网站 ClassLib - 这只是一个包含所有业务逻辑的类lib
类Lib需要与HttpContext Session和Request对象进行交互。这是一个旧的ASP应用程序的代码升级,我已经在其中找到了包含逻辑的所有VBScript并将其放入VB.NET中。我们根本没有时间重写。
我没有使用HttpContext直接与HttpContext进行交互,而我认为它是BAD,也阻止了我们进行单元测试,我引入了以下抽象层:
Public Class Request
Private Shared _requestWrapper as IRequestWrapper
Public Shared ReadOnly Property RequestWrapper()
Get
If _requestWrapper Is Nothing Then
Throw New Exception("_requestWrapper is null. Make sure InitRequest() is called with valid parameters")
End If
Return _requestWrapper
End Get
End Property
Public Shared Sub InitRequest(ByRef requestWrapper As IRequestWrapper)
_requestWrapper = requestWrapper
End Sub
Public Shared Function GetVal(ByVal key As String) As Object
Return RequestWrapper.GetVal(key)
End Function
等
这意味着在单元测试中我可以将自己的MockRequest对象提供给这个Request类,这只是一个简单的NameValue集合。然后ClassLib和网站中的代码只使用Request类,并且它不是来自HttpContext的更明智的,而是来自这个模拟类。
说到真正的交易,我只需要以下(C#)类:
public class RealRequest : IRequestWrapper
{
public void Initialize(HttpContext context)
{
}
#region Implementation of IRequestWrapper
public object GetVal(string index)
{
return HttpContext.Current.Request[index];
}
等
这是在网站的global.asax的Session_Start中初始化的,如下所示:
protected void Session_Start(object sender, EventArgs e)
{
IRequestWrapper requestWrapper = new RealRequest();
WebSession.Request.InitRequest(ref requestWrapper);
}
我认为这与静态网关模式类似。
现在,我知道ASP.NET等多线程环境中的单例和静态变量,但这有点不同。当它到达RequestWrapper.GetVal()时,它实际上转到该运行线程的HttpContext - 并从中拉出值。
当然,我们对多个用户点击同一台服务器的任何并发测试都没有出现任何奇怪的行为。
我只是在寻找重新保证这是一个合理的设计,如果没有,为什么不呢?
由于 邓肯
答案 0 :(得分:1)
这很好。我们的应用程序中有一个非常类似的情况,如果它存在则使用HttpContext
或者否则使用伪实现。
需要注意的一点是,有一个非常具体的实例,其中HttpContext.Current
将返回一个值,但HttpContext.Current.Request
会在Application_Start
事件触发时抛出异常。在框架代码中,您实际上并不知道(或想知道)触发调用的内容。