在为下游依赖项提供值时解析依赖项

时间:2014-07-15 00:52:29

标签: castle-windsor

我一直在尝试使用Windsor和Web API并将HttpRequestMessage注入控制器的下游依赖项中而遇到无穷无尽的问题。由于我已经在Stackoverflow上尝试了所有匹配的答案,我想以不同的方式提出问题:

在Castle Windsor中,如何在为下游依赖项提供值的同时解析组件实例?也就是说,正在解析的组件所需的组件需要提供的值。

对于上下文,我尝试注入HttpRequestMessage,以便我可以使用它来解析请求上下文(主要用于解析绝对URL)。

编辑我还想指出,我目前不依赖于Web Host / System.Web而我宁愿不改变它。

4 个答案:

答案 0 :(得分:0)

正确的方法是

  1. 创建IMyDesiredRouteParameterProvider
  2. 实施它。获取当前请求并获取URL
  3. 注册并通过构造函数将其注入所需的依赖类。
  4. 我自己做了这样一个实现,我可以这样说它工作正常。您可以进行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"];进行了这样的传递。