【问题标题】:How to implement this (HttpContext) dependency in Unity?如何在 Unity 中实现这个(HttpContext)依赖?
【发布时间】:2011-11-01 14:49:00
【问题描述】:

我们有一个依赖于HttpContext 的类。 我们是这样实现的:

public SiteVariation() : this(new HttpContextWrapper(HttpContext.Current))
{
}
public SiteVariation(HttpContextBase context)
{}

现在我要做的是通过Unity 实例化SiteVariation 类,这样我们就可以创建一个构造函数。 但是我不知道如何在Unity中以config方式配置这个新的HttpContextWrapper(HttpContext.Current))

ps 这是我们使用的配置方式

<type type="Web.SaveRequest.ISaveRequestHelper, Common" mapTo="Web.SaveRequest.SaveRequestHelper, Common" />

【问题讨论】:

    标签: c# asp.net inversion-of-control unity-container httpcontext


    【解决方案1】:

    Microsoft 已经围绕 HttpContextHttpRequestHttpResponse 构建了出色的包装器和抽象,它们包含在 .NET 中,因此我肯定会直接使用它们而不是自己包装它们。

    您可以使用 InjectionFactoryHttpContextBase 配置 Unity,如下所示:

    var container = new UnityContainer(); 
    
    container.RegisterType<HttpContextBase>(new InjectionFactory(_ => 
        new HttpContextWrapper(HttpContext.Current)));
    

    另外,如果你需要HttpRequestBase(我用得最多)和HttpResponseBase,你可以这样注册:

    container.RegisterType<HttpRequestBase>(new InjectionFactory(_ => 
        new HttpRequestWrapper(HttpContext.Current.Request)));
    
    container.RegisterType<HttpResponseBase>(new InjectionFactory(_ => 
        new HttpResponseWrapper(HttpContext.Current.Response)));
    

    您可以在单元测试中轻松模拟 HttpContextBaseHttpRequestBaseHttpResponseBase,而无需自定义包装器。

    【讨论】:

    • 你的回答很好,所以这纯粹是一种风格上的选择:因为你在 lamda 中返回一个简单的对象,所以不需要正式的代码块。所以你可以简单地写一行:container.RegisterType(new InjectionFactory(c => new HttpContextWrapper(HttpContext.Current)));
    • @BlackjacketMack 谢谢!是的,我更喜欢这样。我已经用这个更新了答案。为了遵循惯例,我还更新为使用下划线表示该参数未使用。
    • 不错。这是我第一次看到下划线约定,但我喜欢它!非常善于交流。
    【解决方案2】:

    我不会直接依赖HttpContextBase。相反,我会在它周围创建一个包装器,并使用您需要的位:

    public interface IHttpContextBaseWrapper
    {
       HttpRequestBase Request {get;}
       HttpResponseBase Response {get;}
       //and anything else you need
    }
    

    然后是实现:

    public class HttpContextBaseWrapper : IHttpContextBaseWrapper
    {
       public HttpRequestBase Request {get{return HttpContext.Current.Request;}}
       public HttpResponseBase Response {get{return HttpContext.Current.Response;}}
       //and anything else you need
    }
    

    这样,您的类现在只依赖于一个包装器,并且不需要实际的 HttpContext 来运行。使其更容易注入,也更容易测试:

    public SiteVariation(IHttpContextBaseWrapper context)
    {
    
    }
    
    var container = new UnityContainer();
    container.RegisterType<IHttpContextBaseWrapper ,HttpContextBaseWrapper>();
    

    【讨论】:

    • 不错。被包装器困扰,因为这些天似乎一切都被包装了,但在这种情况下,它似乎是一个很好的。
    • 关于“这些天似乎一切都包装好了”:我听到有人说:每年我们都会在去年构建的糟糕代码周围添加新的包装器。这与答案无关,这很好,但它刚刚出现:-)
    • @Michel:这句话有很多道理。随着 DI/IoC 的流行,我一直在围绕许多“遗留”代码(在某些情况下不超过几年的代码)编写包装器,以使其更具可测试性。现在感觉这是正确的做法。从现在起的 3 年内,我们都会说“伙计,我们在想那些一次性的界面!!”
    • .NET 在很大程度上是 Win32 的包装器......也许我们应该回到编写 Win32 代码。 :)
    • 微软现在实现了HttpContextWrapper,所以你不需要自己写
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 2023-04-02
    • 2014-08-16
    • 2020-10-10
    • 2018-05-28
    • 2014-04-26
    • 2012-03-02
    相关资源
    最近更新 更多