0

如何创建 HttContext 实例并将其注册到 StructureMap 配置中?

我有一个使用 StructureMap 的 MVC3 Web 项目,我认为这是一个典型的设置,其中控制器调用存储库类,而存储库类负责业务逻辑和数据库操作。

StructureMap 用于向控制器注入适当的存储库。

但最近,我需要一些存储库来记录某些操作以及用户的 IP 地址。

要获取 IP 地址,我正在使用

requestContext.HttpContext.Request.UserHostAddress

现在,我认为将 HttpContext 传递到 repo 类中,然后在 StructureMap 中注册 HTTContext 依赖关系是很聪明的,如下所示:

For<RequestContext>().Use(ctx => HttpContext.Current.Request.RequestContext);

到目前为止,这是可行的,但我还有一个迷你项目,它将使用相同的 repo 功能,但作为控制台应用程序运行(或者可能是 win 服务)。这里的问题是没有 ASP.Net 运行时就没有 HttpContext。我收到一个运行时错误,说 httpContext 为空。

我怎样才能在那里获得一个 HttpContext ?

编辑 Alexei 和 Plymouth 建议的解决方案

谢谢,如果我理解 Alexei 的建议,我应该制作一个如下界面:

interface ILoggingConext
{
    public string IPAddress { get; set; }
}

然后有 2 个具体类,其中一个 (A) 接受 HTTPContext,另一个 (B) 可以具有 IPAddress 的默认值

然后在 StructureMap 中,对其进行配置,以便在 HttpContext 不为 null 时使用具体类 a。否则,它将使用 B。

我接近了吗?

解决方案

接受 Alexei 的建议,这是我目前使用的解决方案:

首先声明接口和2个具体类

public interface ILoggingContext
{
    string IPAddress { get; set; }
    string HostAddress { get; set; }
}

public class HttpLoggingContext : ILoggingContext
{
    public string IPAddress { get; set; }
    public string HostAddress { get; set; }

    //This is the concrete class to use if context is available, so provide a constructor to accept a context and set properties appropriately
    public HttpLoggingContext(RequestContext rContext)
    {
        if (rContext != null && rContext.HttpContext != null && rContext.HttpContext.Request != null)
        {
            this.IPAddress = rContext.HttpContext.Request.UserHostAddress;
            this.HostAddress = rContext.HttpContext.Request.UserHostName;
        }
    }
}

//No http context, so just set the properties to something that signifies this, using "local" here
public class ConsoleLoggingContext : ILoggingContext
{
    public string IPAddress { get; set; }
    public string HostAddress { get; set; }


    public ConsoleLoggingContext()
    {
        this.IPAddress = "local";
        this.HostAddress = "local";
    }
}

然后这里是 StructureMap 注册表类中的配置:

        For<ILoggingContext>().ConditionallyUse(o =>
            {
                o.If(c => HttpContext.Current!=null && HttpContext.Current.Request!=null && HttpContext.Current.Request.RequestContext!=null).ThenIt.Is.ConstructedBy(a=> new HttpLoggingContext(HttpContext.Current.Request.RequestContext));
                o.TheDefault.IsThis(new ConsoleLoggingContext());

            }
        ).Named("ConditionalILoggingContext");

如果 HttpContext.Current.Request.RequestContext 不为空,我们使用 HttpLoggingContext。否则我们使用 ConsoleLoggingContext。

我将此标记为解决方案。谢谢您的帮助

4

2 回答 2

2

按照你的建议做:

For<RequestContext>().Use(ctx =>
{
    //TODO: Create unittest.html as required.
    SimpleWorkerRequest request = new SimpleWorkerRequest("/unittest", @"c:\inetpub\wwwroot\unittest", "unittest.html", null, new StringWriter());
    HttpContext context = new HttpContext(request);
    return HttpContext.Current = context;
});

但正如建议的那样,抽象对上下文的依赖将是一条更好的路。

于 2013-07-09T23:03:13.343 回答
0

我运行的解决方案是 Alexei 建议的。使用不同的包装器来包含我需要的上下文对象所需的属性,并使用结构映射来决定使用哪个包装器,具体取决于 HttpContext 的存在。请参阅“解决方案”下的示例代码的原始问题。

于 2013-07-10T01:09:51.703 回答