我有几个依赖注入服务,这些服务依赖于HTTP上下文之类的东西。现在我在Application_Start处理程序中将它们配置为单例 Windsor容器,这显然是此类服务的问题。
处理此问题的最佳方法是什么?我正在考虑将它们设置为 transient ,然后在每次HTTP请求后释放它们。但是将HTTP上下文注入其中的最佳方式/地点是什么?控制器工厂或其他地方?
答案 0 :(得分:24)
就像Mark说的那样,你需要将这些依赖于http的服务注册为PerWebRequest或Transient。这是一个示例,说明如何注册和注入HttpRequest或HttpContext:
public class Service {
private readonly HttpRequestBase request;
public Service(HttpRequestBase request) {
this.request = request;
}
public string RawUrl {
get {
return request.RawUrl;
}
}
}
...
protected void Application_Start(object sender, EventArgs e) {
IWindsorContainer container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();
container.AddComponentLifeStyle<Service>(LifestyleType.Transient);
container.Register(Component.For<HttpRequestBase>()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpRequestWrapper(HttpContext.Current.Request)));
container.Register(Component.For<HttpContextBase>()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current)));
}
使用HttpRequestBase
代替HttpRequest
,您可以轻松地将其模拟出来进行测试。
另外,不要忘记在web.config中注册PerWebRequestLifestyleModule
。
答案 1 :(得分:5)
使用Castle Windsor,您可以使用PerWebRequest
生命周期 - 这应该与您的要求非常吻合。
这意味着您可以将HTTP内容注入您的服务,容器将负责适当的生命周期管理。但是,这需要您将所有这些服务(以及这些服务的所有使用者等)注册为PerWebRequest(或Transient),因为如果您将它们注册为Singletons,它们将保持陈旧(并且可能处置)的上下文。 / p>
答案 2 :(得分:4)
我刚遇到了同样的问题,但我的解决方案有所不同。
界面:
public interface IHttpContextProvider
{
/// <summary>
/// Gets the current HTTP context.
/// </summary>
/// <value>The current HTTP context.</value>
HttpContextBase Current { get; }
}
实现:
/// <summary>
/// A default HTTP context provider, returning a <see cref="HttpContextWrapper"/> from <see cref="HttpContext.Current"/>.
/// </summary>
public class DefaultHttpContextProvider : IHttpContextProvider
{
public HttpContextBase Current
{
get { return new HttpContextWrapper(HttpContext.Current); }
}
}
然后我将IHttpContextProvider
注册为容器中的单身人士。
对于DI来说,我仍然是一个新手,所以也许我过于复杂化,但从我能理解的,我不能有任何单件组件取决于PerWebRequest生活方式组件,这是有道理的(但是这就是所有例子的作用)。在我的解决方案中,我依赖HttpContext.Current
在一个孤立的组件中,我对测试它不感兴趣。但是,每个需要访问HTTP上下文的组件都可以通过依赖IHttpContextProvider
来获取它,并根据需要轻松模拟它。
我真的过于复杂化,或者我的解决方案有什么警告吗?