c# – ASP Web Api – IoC – 解析HttpRequestMessage

前端之家收集整理的这篇文章主要介绍了c# – ASP Web Api – IoC – 解析HttpRequestMessage前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正试图用ASP.NET WebAPI设置Castle Windsor.

我也使用Hyprlinkr包(https://github.com/ploeh/Hyprlinkr),因此需要一个HttpRequestMessage的实例注入到我的控制器的一个依赖项中.

我正在跟随Mark Seemann – http://blog.ploeh.dk/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx的这篇文章,但是我发现尽管API运行,但是当我打电话时,请求就挂起来了.没有错误信息.就好像它处于无限循环.它挂在我的Custom ControllerActivator中的Resolve的调用

我想我的一些城堡注册错了.如果我删除上述文章中提到的那些,那么我可以成功地调用API(尽管没有需要解决的依赖关系)

有任何想法吗?

代码在下面

//Global.asax
public class WebApiApplication : HttpApplication
{
    private readonly IWindsorContainer container;

    public WebApiApplication()
    {
        container = 
            new WindsorContainer(
                new DefaultKernel(
                    new InlineDependenciesPropagatingDependencyResolver(),new DefaultProxyFactory()),new DefaultComponentInstaller());

        container.Install(new DependencyInstaller());
    }

    protected void Application_Start()
    {        
        GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator),new WindsorCompositionRoot(this.container));
    }

// installer
public class DependencyInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container,IConfigurationStore store)
    {
        container.AddFacility<TypedFactoryFacility>();

        container.Register(
            Component.For<ValuesController>()
                .Named("ValuesController")
                .LifeStyle.PerWebRequest,Component.For<IResourceLinker>()
                .ImplementedBy<RouteLinker>()
                .LifeStyle.PerWebRequest,Component.For<IResourceModelBuilder>()
                .ImplementedBy<ResourceModelBuilder>()
                .LifeStyle.PerWebRequest,Component.For<HttpRequestMessage>()
                .Named("HttpRequestMessage")
                .LifeStyle.PerWebRequest
            );
    }
}

//Activator

public class WindsorCompositionRoot : IHttpControllerActivator
{
    private readonly IWindsorContainer container;

    public WindsorCompositionRoot(IWindsorContainer container)
    {
        this.container = container;
    }

    public IHttpController Create(
        HttpRequestMessage request,HttpControllerDescriptor controllerDescriptor,Type controllerType)
    {
        var controller = (IHttpController)this.container.Resolve(controllerType,new { request = request });

        request.RegisterForDispose(
            new Release(
                () => this.container.Release(controller)));

        return controller;
    }

// DependencyResolver   
public class InlineDependenciesPropagatingDependencyResolver : DefaultDependencyResolver
{
    protected override CreationContext RebuildContextForParameter(CreationContext current,Type parameterType)
    {
        if (parameterType.ContainsGenericParameters)
        {
            return current;
        }

        return new CreationContext(parameterType,current,true);
    }
}

编辑***********
附加信息****************

所以我设置了一个场景,控制器只需要一个HttpRequestMessage作为一个ctor参数,并发现:

这样做:

//controller
public class ValuesController : ApiController
    {
        private readonly HttpRequestMessage _httpReq;

        public ValuesController(HttpRequestMessage httpReq)
        {
            _httpReq = httpReq;
        }
//IHttpControllerActivator
public IHttpController Create(
            HttpRequestMessage httpRequest,Type controllerType)
        {

            var controller = (IHttpController)this.container.Resolve(
                controllerType,new { httpReq = httpRequest });

            return controller;

但是,这不是.

//controller
public class ValuesController : ApiController
    {
        private readonly HttpRequestMessage _httpReq;

        public ValuesController(HttpRequestMessage request)
        {
            _httpReq = request;
        }

//IHttpControllerActivator
public IHttpController Create(
            HttpRequestMessage request,new { request = request });

            return controller;

即当anon对象具有称为“请求”的属性,并且控制器ctor arg被称为“请求”时.它以某种方式使控制器认为它的请求属性为null.这是什么原因导致我看到的错误

Cannot reuse an ‘ApiController’ instance. ‘ApiController’ has to be
constructed per incoming message. Check your custom
‘IHttpControllerActivator’ and make sure that it will not manufacture
the same instance.

at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext
controllerContext,CancellationToken cancellationToken) at
System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage
request,CancellationToken cancellationToken) at
System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage
request,CancellationToken cancellationToken)

读了这个
How can I enrich object composition in StructureMap without invoking setter injection?

它解释了类似的情况.

当然,hyprlinkr具有称为“request”的HttpRequestMessage的ctor参数,因此我需要使用该属性名称指定anon对象.

有任何想法吗?

解决方法

这是一个适用于我的组合根:
public class WindsorCompositionRoot : IHttpControllerActivator
{
    private readonly IWindsorContainer container;

    public WindsorCompositionRoot(IWindsorContainer container)
    {
        this.container = container;
    }

    public IHttpController Create(
        HttpRequestMessage request,Type controllerType)
    {
        var controller = (IHttpController)this.container.Resolve(
            controllerType,new
            {
                request = request
            });

        request.RegisterForDispose(
            new Release(
                () => this.container.Release(controller)));
        return controller;
    }

    private class Release : IDisposable
    {
        private readonly Action release;

        public Release(Action release)
        {
            this.release = release;
        }

        public void Dispose()
        {
            this.release();
        }
    }
}

以下是我创建容器的方式:

this.container =
    new WindsorContainer(
        new DefaultKernel(
            new InlineDependenciesPropagatingDependencyResolver(),new DefaultComponentInstaller())
        .Install(new MyWindsorInstaller());

这里是InlineDependenciesPropagatingDependencyResolver:

public class InlineDependenciesPropagatingDependencyResolver : 
    DefaultDependencyResolver
{
    protected override CreationContext RebuildContextForParameter(
        CreationContext current,true);
    }
}

最后,我如何注册RouteLinker:

container.Register(Component
    .For<RouteLinker,IResourceLinker>()
    .LifestyleTransient());

需要注意的一点是,ApiController基类有一个名为Request of HttpRequestMessage类型的公共属性.如my book节第10.4.3节所述,Windsor将尝试为每个可写属性分配一个值(如果它具有匹配的组件),并且匹配不区分大小写.

当您将HttpRequestMessage命名请求传递给Resolve方法时,这正是发生的情况,因此您需要告诉Castle Windsor它应该放弃ApiControllers的属性注入.以下是我在公约注册中如何使用:

container.Register(Classes
    .FromThisAssembly()
    .BasedOn<IHttpController>()
    .ConfigureFor<ApiController>(c => c.Properties(pi => false))
    .LifestyleTransient());
原文链接:https://www.f2er.com/csharp/96788.html

猜你在找的C#相关文章