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;
}
}
}