DefaultComplexConverter
using Castle.Core.Configuration;
using Castle.Core.Internal;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Reflection;
namespace Castle.MicroKernel.SubSystems.Conversion
{
[Serializable]
public class DefaultComplexConverter : AbstractTypeConverter
{
private IConversionManager conversionManager;
private IConversionManager ConversionManager {
get {
if (conversionManager == null)
conversionManager = base.Context.Kernel.GetConversionManager();
return conversionManager;
}
}
public override bool CanHandleType(Type type)
{
return !type.GetTypeInfo().IsPrimitive;
}
public override object PerformConversion(IConfiguration configuration, Type targetType)
{
object obj = CreateInstance(targetType, configuration);
ConvertPropertyValues(obj, targetType, configuration);
return obj;
}
public override object PerformConversion(string value, Type targetType)
{
throw new NotImplementedException();
}
private object CreateInstance(Type type, IConfiguration configuration)
{
type = ObtainImplementation(type, configuration);
ConstructorInfo constructorInfo = ChooseConstructor(type);
object[] ctorArgs = null;
if (constructorInfo != (ConstructorInfo)null)
ctorArgs = ConvertConstructorParameters(constructorInfo, configuration);
return type.CreateInstance<object>(ctorArgs);
}
private Type ObtainImplementation(Type type, IConfiguration configuration)
{
string value = ((NameValueCollection)configuration.get_Attributes())["type"];
if (string.IsNullOrEmpty(value)) {
if (type.GetTypeInfo().IsInterface)
throw new ConverterException("A type attribute must be specified for interfaces");
return type;
}
Type type2 = base.Context.Composition.PerformConversion<Type>(value);
if (!type.IsAssignableFrom(type2))
throw new ConverterException($"""{type2.FullName}""{type.FullName}");
return type2;
}
private ConstructorInfo ChooseConstructor(Type type)
{
ConstructorInfo constructorInfo = null;
ConstructorInfo[] constructors = type.GetConstructors();
foreach (ConstructorInfo constructorInfo2 in constructors) {
if (constructorInfo2.GetParameters().Length != 0) {
if (constructorInfo != (ConstructorInfo)null)
throw new ConverterException("Classes with more than one non-default constructor are not supported.");
constructorInfo = constructorInfo2;
}
}
return constructorInfo;
}
private object[] ConvertConstructorParameters(ConstructorInfo constructor, IConfiguration configuration)
{
IConversionManager conversionManager2 = ConversionManager;
ParameterInfo[] parameters = constructor.GetParameters();
object[] array = new object[parameters.Length];
int i = 0;
for (int num = parameters.Length; i < num; i++) {
ParameterInfo parameterInfo = parameters[i];
IConfiguration val = FindChildIgnoreCase(configuration, parameterInfo.Name);
if (val == null)
throw new ConverterException($"""{parameterInfo.Name}""{configuration.get_Name()}""");
Type parameterType = parameterInfo.ParameterType;
if (!ConversionManager.CanHandleType(parameterType))
throw new ConverterException($"""{parameterInfo.Name}""{configuration.get_Name()}""{parameterType.Name}""");
array[i] = ConvertChildParameter(val, parameterType);
}
return array;
}
private void ConvertPropertyValues(object instance, Type type, IConfiguration configuration)
{
IConversionManager conversionManager2 = ConversionManager;
foreach (IConfiguration item in (List<IConfiguration>)configuration.get_Children()) {
PropertyInfo property = type.GetProperty(item.get_Name(), BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
if (!(property == (PropertyInfo)null) && property.CanWrite) {
Type propertyType = property.PropertyType;
if (!ConversionManager.CanHandleType(propertyType))
throw new ConverterException($"""{property.Name}""{configuration.get_Name()}""{propertyType.Name}""");
object value = ConvertChildParameter(item, propertyType);
property.SetValue(instance, value, null);
}
}
}
private object ConvertChildParameter(IConfiguration config, Type type)
{
if (config.get_Value() == null && ((List<IConfiguration>)config.get_Children()).Count != 0)
return base.Context.Composition.PerformConversion(config, type);
return base.Context.Composition.PerformConversion(config.get_Value(), type);
}
private IConfiguration FindChildIgnoreCase(IConfiguration config, string name)
{
foreach (IConfiguration item in (List<IConfiguration>)config.get_Children()) {
if (CultureInfo.CurrentCulture.CompareInfo.Compare(item.get_Name(), name, CompareOptions.IgnoreCase) == 0)
return item;
}
return null;
}
}
}