导致错误的原因“看起来您忘记注册http模块Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule”?

时间:2014-08-22 08:20:51

标签: c# asp.net-web-api asp.net-web-api2 owin castle-windsor

我使用castle.windsor和owin在webapi2中使用了一些DI。这是相关的代码:

[assembly: OwinStartup(typeof(Bla.Startup))]
    namespace Bla
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                //...  
                var container = new WindsorContainer().Install(new ControllerInstaller());
                var httpDependencyResolver = new WindsorHttpDependencyResolver(container);
                config.DependencyResolver = httpDependencyResolver;
                //...
            }
    }

    public class ControllerInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(AllTypes.FromThisAssembly()
            .Pick().If(t => t.Name.EndsWith("Controller"))
            .Configure(configurer => configurer.Named(configurer.Implementation.Name))
            .LifestylePerWebRequest());

            //...
        }
    }

    internal class WindsorDependencyScope : IDependencyScope
    {
        private readonly IWindsorContainer _container;
        private readonly IDisposable _scope;

        public WindsorDependencyScope(IWindsorContainer container)
        {
            if (container == null)
            {
            throw new ArgumentNullException("container");
            }

            _container = container;
            _scope = container.BeginScope();
        }

        public object GetService(Type t)
        {
            return _container.Kernel.HasComponent(t)
            ? _container.Resolve(t) : null;
        }

        public IEnumerable<object> GetServices(Type t)
        {
            return _container.ResolveAll(t)
            .Cast<object>().ToArray();
        }

        public void Dispose()
        {
            _scope.Dispose();
        }
    }

    internal sealed class WindsorHttpDependencyResolver : IDependencyResolver
    {
        private readonly IWindsorContainer _container;

        public WindsorHttpDependencyResolver(IWindsorContainer container)
        {
            if (container == null)
            {
            throw new ArgumentNullException("container");
            }

            _container = container;
        }

        public object GetService(Type t)
        {
            return _container.Kernel.HasComponent(t)
             ? _container.Resolve(t) : null;
        }

        public IEnumerable<object> GetServices(Type t)
        {
            return _container.ResolveAll(t)
            .Cast<object>().ToArray();
        }

        public IDependencyScope BeginScope()
        {
            return new WindsorDependencyScope(_container);
        }

        public void Dispose()
        {
        }
    }

owin的一个很大的优点是它删除了依赖形式system.web。这允许从其他事物中实现相当有效(在内存中?)集成测试。我面临的问题是:

config.DependencyResolver = httpDependencyResolver;

引入了对系统的依赖。所以当我尝试运行这样一个简单的测试时:

private TestServer _server;

    [TestFixtureSetUp]
    public void FixtureInit()
    {
        _server = TestServer.Create<Startup>();
    }

    [Test]
    public voidSomeTest()
    {
        using (var server = TestServer.Create<Startup>())
        {
        HttpResponseMessage response = server.HttpClient.GetAsync("/api/bladibla/test").Result;

        // ...
        }
    }

我明白了:

{"Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule\r\nTo fix this add\r\n<add name=\"PerRequestLifestyle\" type=\"Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor\" />\r\nto the <httpModules> section on your web.config.\...

我可以在测试项目的app.config中注册一些东西吗?任何反馈都会非常受欢迎。

PS:

我尝试添加:

<system.web>
    <httpModules>
      <add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
    </httpModules>
  </system.web>
  <system.webServer>
    <modules>
      <add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
    </modules>
  </system.webServer>

到app.config但没有成功。

PPS:

好的,如果我改变了:

container.Register(AllTypes.FromThisAssembly()
                .Pick().If(t => t.Name.EndsWith("Controller"))
                .Configure(configurer => configurer.Named(configurer.Implementation.Name))
                .LifestylePerWebRequest());

为:

container.Register(AllTypes.FromThisAssembly()
                .Pick().If(t => t.Name.EndsWith("Controller"))
                .Configure(configurer => configurer.Named(configurer.Implementation.Name))
                .LifestyleTransient());

它有效,这是有道理的。最大的问题是,我如何动态更改它,具体取决于它是在部署/适当的Web环境还是测试环境中。

2 个答案:

答案 0 :(得分:4)

  

{&#34;看起来您忘记注册http模块Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule \ r \ n要修复此添加\ r \ n \ r \ n \ n \ n在web.config上的部分....

但你试图注册:

  

PerRequestLifestyle

看到区别? PerWebRequestLifestyle不是PerRequestLifeStyle。

看一下Mauricio Scheffer`s HybridLifeStyles,它可以非常容易地设置容器进行测试。

答案 1 :(得分:0)

在使用OWIN进行内存测试时,我使用以下扩展方法来覆盖行为:

private static void OverridePerWebRequestLifestyle(this IWindsorContainer container)
{
    container.Kernel.ComponentModelCreated += model =>
    {
        if (model.LifestyleType == LifestyleType.PerWebRequest)
        {
            model.LifestyleType = LifestyleType.Transient;
        }
    };
}