Testing Castle windsor Component with PerWebRequest lifestyle

后端 未结 4 2000
夕颜
夕颜 2020-12-31 02:00

I\'m trying to do some testing with castle windsor involved, in one of my tests I want to check the windsor installers, so I check that the container can resolve my componen

相关标签:
4条回答
  • 2020-12-31 02:37

    I ended up implementing this extension. ATTN: Must call before loading components with the PerWebRequest lifestyle:

    public static class WindsorContainerExtensions
    {
        public static IWindsorContainer OverridePerWebRequestLifestyle(this IWindsorContainer container)
        {
            container.Kernel.ComponentModelCreated += model =>
            {
                if (model.IsPerWebRequestLifestyle())
                {
                    model.LifestyleType = LifestyleType.Transient;
                }
            };
    
            return container;
        }
    
        private static bool IsPerWebRequestLifestyle(this ComponentModel model)
        {
            return model.LifestyleType == LifestyleType.Scoped
                && model.HasAccessorType(typeof(WebRequestScopeAccessor));
        }
    
        private static bool HasAccessorType(this ComponentModel model, Type type)
            => model.HasExtendedProperty("castle.scope-accessor-type", type);
    
        private static bool HasExtendedProperty<T>(this ComponentModel model, object key, T expected)
        {
            return model.ExtendedProperties[key] is T actual
                && EqualityComparer<T>.Default.Equals(actual, expected);
        }
    }
    

    Requires these imports:

    using System;
    using System.Collections.Generic;
    using Castle.Core;
    using Castle.Facilities.AspNet.SystemWeb;
    using Castle.Windsor;
    
    0 讨论(0)
  • 2020-12-31 02:46

    In your test you could subscribe to the ComponentModelCreated event and change the lifestyle of your per-web-request components to something else. (example).

    If you're writing an integration test with the scope of a single request, singleton should do.

    If you're writing an integration test that spans multiple requests, you could use a contextual lifestyle to simulate the scope of requests.

    Edit: including code from example (which is no longer available):

    container.Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;
    

    void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
    {
        if (model.LifestyleType == LifestyleType.Undefined)
            model.LifestyleType = LifestyleType.Transient;
    }
    
    0 讨论(0)
  • 2020-12-31 02:51

    From version 5 of Windsor the accepted answer doesn't work if you are using Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor because the PerWebRequest lifestyle is already a scoped lifestyle.

    I got it to work by changing the the ComponentModelCreated delegate to the following:

    void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
    {
        const string CastleScopeAccessorType = "castle.scope-accessor-type";
    
        if (model.ExtendedProperties.Contains(CastleScopeAccessorType))
        {
            model.ExtendedProperties.Remove(CastleScopeAccessorType);
        }
    }
    
    0 讨论(0)
  • 2020-12-31 02:51

    If you also want to check if the type of scope is per web request you could also do this

    var isPerWebRequestScope = JsonConvert.SerializeObject(model.ExtendedProperties).Contains("Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor")
    
    0 讨论(0)
提交回复
热议问题