<PackageReference Include="Castle.Windsor" Version="6.0.0" />

LifestyleModelInspector

Inspects the component configuration and the type looking for a definition of lifestyle type. The configuration preceeds whatever is defined in the component.
using Castle.Core; using Castle.Core.Internal; using Castle.MicroKernel.Lifestyle.Scoped; using Castle.MicroKernel.SubSystems.Conversion; using System; using System.Collections.Specialized; using System.Linq; using System.Reflection; namespace Castle.MicroKernel.ModelBuilder.Inspectors { [Serializable] public class LifestyleModelInspector : IContributeComponentModelConstruction { private readonly IConversionManager converter; public LifestyleModelInspector(IConversionManager converter) { this.converter = converter; } public virtual void ProcessModel(IKernel kernel, ComponentModel model) { if (!ReadLifestyleFromConfiguration(model)) ReadLifestyleFromType(model); } protected virtual bool ReadLifestyleFromConfiguration(ComponentModel model) { if ((object)model.Configuration == null) return false; string text = ((NameValueCollection)model.Configuration.get_Attributes())["lifestyle"]; if (text != null) { LifestyleType lifestyleType2 = model.LifestyleType = converter.PerformConversion<LifestyleType>(text); switch (lifestyleType2) { case LifestyleType.Singleton: case LifestyleType.Thread: case LifestyleType.Transient: return true; case LifestyleType.Pooled: ExtractPoolConfig(model); return true; case LifestyleType.Custom: { Type mandatoryTypeFromAttribute = GetMandatoryTypeFromAttribute(model, "customLifestyleType", lifestyleType2); ValidateTypeFromAttribute(mandatoryTypeFromAttribute, typeof(ILifestyleManager), "customLifestyleType"); model.CustomLifestyle = mandatoryTypeFromAttribute; return true; } case LifestyleType.Scoped: { Type typeFromAttribute2 = GetTypeFromAttribute(model, "scopeAccessorType"); if (typeFromAttribute2 != (Type)null) { ValidateTypeFromAttribute(typeFromAttribute2, typeof(IScopeAccessor), "scopeAccessorType"); model.ExtendedProperties[Constants.ScopeAccessorType] = typeFromAttribute2; } return true; } case LifestyleType.Bound: { Type typeFromAttribute = GetTypeFromAttribute(model, "scopeRootBinderType"); if (typeFromAttribute != (Type)null) { Func<IHandler[], IHandler> value = ExtractBinder(typeFromAttribute, model.Name); model.ExtendedProperties[Constants.ScopeRootSelector] = value; } return true; } default: throw new InvalidOperationException($"""{model.Name}""{lifestyleType2}"""); } } Type typeFromAttribute3 = GetTypeFromAttribute(model, "scopeRootBinderType"); if (typeFromAttribute3 != (Type)null) { Func<IHandler[], IHandler> value2 = ExtractBinder(typeFromAttribute3, model.Name); model.ExtendedProperties[Constants.ScopeRootSelector] = value2; model.LifestyleType = LifestyleType.Bound; return true; } Type typeFromAttribute4 = GetTypeFromAttribute(model, "scopeAccessorType"); if (typeFromAttribute4 != (Type)null) { ValidateTypeFromAttribute(typeFromAttribute4, typeof(IScopeAccessor), "scopeAccessorType"); model.ExtendedProperties[Constants.ScopeAccessorType] = typeFromAttribute4; model.LifestyleType = LifestyleType.Scoped; return true; } Type typeFromAttribute5 = GetTypeFromAttribute(model, "customLifestyleType"); if (typeFromAttribute5 != (Type)null) { ValidateTypeFromAttribute(typeFromAttribute5, typeof(ILifestyleManager), "customLifestyleType"); model.CustomLifestyle = typeFromAttribute5; model.LifestyleType = LifestyleType.Custom; return true; } return false; } protected virtual void ReadLifestyleFromType(ComponentModel model) { LifestyleAttribute[] attributes = model.Implementation.GetAttributes<LifestyleAttribute>(true); if (attributes.Length != 0) { LifestyleAttribute lifestyleAttribute = attributes[0]; model.LifestyleType = lifestyleAttribute.Lifestyle; if (model.LifestyleType == LifestyleType.Custom) { CustomLifestyleAttribute customLifestyleAttribute = (CustomLifestyleAttribute)lifestyleAttribute; ValidateTypeFromAttribute(customLifestyleAttribute.CustomLifestyleType, typeof(ILifestyleManager), "CustomLifestyleType"); model.CustomLifestyle = customLifestyleAttribute.CustomLifestyleType; } else if (model.LifestyleType == LifestyleType.Pooled) { PooledAttribute pooledAttribute = (PooledAttribute)lifestyleAttribute; model.ExtendedProperties[ExtendedPropertiesConstants.Pool_InitialPoolSize] = pooledAttribute.InitialPoolSize; model.ExtendedProperties[ExtendedPropertiesConstants.Pool_MaxPoolSize] = pooledAttribute.MaxPoolSize; } else if (model.LifestyleType == LifestyleType.Bound) { Func<IHandler[], IHandler> value = ExtractBinder(((BoundToAttribute)lifestyleAttribute).ScopeRootBinderType, model.Name); model.ExtendedProperties[Constants.ScopeRootSelector] = value; } else if (model.LifestyleType == LifestyleType.Scoped) { ScopedAttribute scopedAttribute = (ScopedAttribute)lifestyleAttribute; if (scopedAttribute.ScopeAccessorType != (Type)null) { ValidateTypeFromAttribute(scopedAttribute.ScopeAccessorType, typeof(IScopeAccessor), "ScopeAccessorType"); model.ExtendedProperties[Constants.ScopeAccessorType] = scopedAttribute.ScopeAccessorType; } } } } protected virtual void ValidateTypeFromAttribute(Type typeFromAttribute, Type expectedInterface, string attribute) { if (expectedInterface.IsAssignableFrom(typeFromAttribute)) return; throw new InvalidOperationException(string.Format("The Type '{0}' specified in the '{2}' attribute must implement {1}", typeFromAttribute.FullName, expectedInterface.FullName, attribute)); } private Func<IHandler[], IHandler> ExtractBinder(Type scopeRootBinderType, string name) { MemberInfo memberInfo = scopeRootBinderType.GetTypeInfo().FindMembers(MemberTypes.Method, BindingFlags.Instance | BindingFlags.Public, IsBindMethod, null).FirstOrDefault(); if (memberInfo == (MemberInfo)null) throw new InvalidOperationException($"""{scopeRootBinderType.Name}""{name}"""); object target = scopeRootBinderType.CreateInstance<object>(Array.Empty<object>()); return (Func<IHandler[], IHandler>)((MethodInfo)memberInfo).CreateDelegate(typeof(Func<IHandler[], IHandler>), target); } private void ExtractPoolConfig(ComponentModel model) { string text = ((NameValueCollection)model.Configuration.get_Attributes())["initialPoolSize"]; string text2 = ((NameValueCollection)model.Configuration.get_Attributes())["maxPoolSize"]; if (text != null) { int num = converter.PerformConversion<int>(text); model.ExtendedProperties[ExtendedPropertiesConstants.Pool_InitialPoolSize] = num; } if (text2 != null) { int num2 = converter.PerformConversion<int>(text2); model.ExtendedProperties[ExtendedPropertiesConstants.Pool_MaxPoolSize] = num2; } } private Type GetMandatoryTypeFromAttribute(ComponentModel model, string attribute, LifestyleType lifestyleType) { string text = ((NameValueCollection)model.Configuration.get_Attributes())[attribute]; if (text == null) throw new InvalidOperationException($"""{model.Name}""{lifestyleType}""{attribute}"""); return converter.PerformConversion<Type>(text); } private Type GetTypeFromAttribute(ComponentModel model, string attribute) { string text = ((NameValueCollection)model.Configuration.get_Attributes())[attribute]; if (text == null) return null; return converter.PerformConversion<Type>(text); } private bool IsBindMethod(MemberInfo methodMember, object _) { MethodInfo methodInfo = (MethodInfo)methodMember; if (methodInfo.ReturnType != typeof(IHandler)) return false; ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 1) return false; if (parameters[0].ParameterType != typeof(IHandler[])) return false; return true; } } }