我一直在尝试使用Windsor和Web API并将HttpRequestMessage注入控制器的下游依赖项中而遇到无穷无尽的问题。由于我已经在Stackoverflow上尝试了所有匹配的答案,我想以不同的方式提出问题:
在Castle Windsor中,如何在为下游依赖项提供值的同时解析组件实例?也就是说,正在解析的组件所需的组件需要提供的值。
对于上下文,我尝试注入HttpRequestMessage,以便我可以使用它来解析请求上下文(主要用于解析绝对URL)。
编辑我还想指出,我目前不依赖于Web Host / System.Web而我宁愿不改变它。
答案 0 :(得分:0)
正确的方法是
我自己做了这样一个实现,我可以这样说它工作正常。您可以进行Web.Infrastructure程序集并将实现放在那里。如果要从其他Web模块引用它,请将接口和实现放在那里。
using System;
using System.Web;
namespace RouteParameterProvider
{
interface IMyRouteParameterProvider
{
string GetRouteParameter();
}
public class ControllerActionMethodRouteParameterProvider : IMyRouteParameterProvider
{
public string GetRouteParameter()
{
string Parameter = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"] as string;
if (string.IsNullOrEmpty(Parameter))
{
throw new InvalidOperationException();
}
return Parameter;
}
}
}
您可以获取请求上下文包含的所有内容:
HttpContext.Current.Request.RequestContext
如果你重新考虑你的设计决定会更好:
我需要在创建每个之前对HttpRequestMessage进行注册 SomethingController的实例,以便它可以在 LinkGenerator图层。
容器将在运行时初始化,然后用于解析。
答案 1 :(得分:0)
我需要在创建每个之前对HttpRequestMessage进行注册 SomethingController的实例,以便它可以在 LinkGenerator图层。
听起来你想在运行时,启动后注册一个容器。一般来说,这不是一个好习惯 - 注册应该是在应用程序启动时发生的离散事件,并且在运行时不应更改容器的状态。
依赖注入是关于解析服务组件,而不是运行时状态 - 状态通常通过方法传递(方法注入)。在这种情况下,听起来您的LinkGenerator组件需要访问请求的环境状态。
我对HttpRequestMessage并不熟悉,但是this answer似乎表明可以从HttpContext.Current中检索它。你可以在LinkGenerator类上创建一个方法,或者将这个调用包装在一个单独的组件中,该组件被注入到LinkGenerator(HttpRequestMessageProvider?)中。后者将是我的首选方法,因为它允许LinkGenerator更易于测试。
答案 2 :(得分:0)
鉴于缺乏干净的方法,而且Web API没有提供超出每个请求上下文对象的托管端点的信息,我最终从配置中注入了基本URL。
答案 3 :(得分:0)
Mark Seemann的this库是答案吗?在描述中,他明确写道:
这种方法可以使用依赖注入(DI),因为 请求可以注入需要它的服务。
然后给出一个例子:
//在ApiController内部
var uri = this.Url.GetLink(a => a.GetById(1337));
然后您可以通过它在您在控制器中注入的服务中传递URL。
更新: Mark Seemann写了同样的问题here:
"因为HttpRequestMessage提供了您可能需要的上下文 撰写依赖图,最佳可扩展性点是 扩展点,每次提供一个HttpRequestMessage 应该组成图形。这个可扩展点就是 IHttpControllerActivator接口:..."
这样,您可以通过从HttpRequestMessage获取并将其传递给DI容器,将请求上下文信息传递到对象图深处的组件。 只需看看IHttpControllerActivator的界面即可。
WEB API框架通过DependencyResolver获取IHttpControllerActivator。您可能已经使用CastleWindsorDependencyResolver替换了它。现在你必须实现并注册你的HttpControllerActivator并注册它。
当WEB API框架从DependencyResolver(您的Castle Windsor DR)获取IHttpControllerActivator并调用IHttpControllerActivator.Create()时,它将向您传递HttpRequestMessage。您可以从那里获取信息并将其传递给CastleDR,然后再调用Resolve(typeof(MyController))来解析整个对象图 - 这意味着您将MyHttpContextInfo注入到深层分辨率堆栈中的XYZComponent中。
这种方式在最后可能的时刻传递参数,但它仍然是可能的。在温莎城堡中,我通过CreationContext.AdditionalArguments [" myArgument"];进行了这样的传递。