DefaultComponentActivator
Standard implementation of  IComponentActivator. Handles the selection of the best constructor, fills the writable properties the component exposes, run the commission and
            	decommission lifecycles, etc.
            
                using Castle.Core;
using Castle.Core.Internal;
using Castle.DynamicProxy;
using Castle.MicroKernel.Context;
using System;
using System.Reflection;
namespace Castle.MicroKernel.ComponentActivator
{
    [Serializable]
    public class DefaultComponentActivator : AbstractComponentActivator
    {
        internal const string InstanceStash = "castle.component-activator-instance";
        public DefaultComponentActivator(ComponentModel model, IKernelInternal kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)
            : base(model, kernel, onCreation, onDestruction)
        {
        }
        protected override object InternalCreate(CreationContext context)
        {
            object obj = Instantiate(context);
            context.SetContextualProperty("castle.component-activator-instance", obj);
            SetUpProperties(obj, context);
            ApplyCommissionConcerns(obj);
            return obj;
        }
        protected override void InternalDestroy(object instance)
        {
            ApplyDecommissionConcerns(instance);
        }
        protected virtual object Instantiate(CreationContext context)
        {
            ConstructorCandidate constructor = SelectEligibleConstructor(context);
            object[] arguments = CreateConstructorArguments(constructor, context);
            return CreateInstance(context, constructor, arguments);
        }
        protected virtual object CreateInstance(CreationContext context, ConstructorCandidate constructor, object[] arguments)
        {
            object obj = null;
            Type implementation = base.Model.Implementation;
            bool num = base.Kernel.ProxyFactory.ShouldCreateProxy(base.Model);
            if (!num && base.Model.Implementation.GetTypeInfo().get_IsAbstract())
                throw new ComponentRegistrationException(string.Format("Type {0} is abstract.{2} As such, it is not possible to instansiate it as implementation of service '{1}'. Did you forget to proxy it?", base.Model.Implementation.FullName, base.Model.Name, Environment.NewLine));
            bool flag = true;
            if (num)
                flag = base.Kernel.ProxyFactory.RequiresTargetInstance(base.Kernel, base.Model);
            if (flag)
                obj = CreateInstanceCore(constructor, arguments, implementation);
            if (num)
                try {
                    return base.Kernel.ProxyFactory.Create(base.Kernel, obj, base.Model, context, arguments);
                } catch (Exception innerException) {
                    if (arguments != null) {
                        foreach (object instance in arguments) {
                            base.Kernel.ReleaseComponent(instance);
                        }
                    }
                    throw new ComponentActivatorException("ComponentActivator: could not proxy " + base.Model.Implementation.FullName, innerException, base.Model);
                }
            return obj;
        }
        protected object CreateInstanceCore(ConstructorCandidate constructor, object[] arguments, Type implType)
        {
            try {
                return implType.CreateInstance<object>(arguments);
            } catch (Exception ex) {
                if (arguments != null) {
                    foreach (object instance in arguments) {
                        base.Kernel.ReleaseComponent(instance);
                    }
                }
                if (ex is ComponentActivatorException)
                    throw;
                throw new ComponentActivatorException("ComponentActivator: could not instantiate " + base.Model.Implementation.FullName, ex, base.Model);
            }
        }
        protected virtual ConstructorCandidate SelectEligibleConstructor(CreationContext context)
        {
            if (base.Model.Constructors.Count == 0)
                return null;
            if (base.Model.Constructors.Count == 1)
                return base.Model.Constructors[0];
            ConstructorCandidate constructorCandidate = null;
            int winnerPoints = 0;
            foreach (ConstructorCandidate constructor in base.Model.Constructors) {
                if (CheckCtorCandidate(constructor, context, out int candidatePoints) && BestScoreSoFar(candidatePoints, winnerPoints, constructorCandidate)) {
                    if (BestPossibleScore(constructor, candidatePoints))
                        return constructor;
                    constructorCandidate = constructor;
                    winnerPoints = candidatePoints;
                }
            }
            if (constructorCandidate == null)
                throw new NoResolvableConstructorFoundException(base.Model.Implementation, base.Model);
            return constructorCandidate;
        }
        private static bool BestScoreSoFar(int candidatePoints, int winnerPoints, ConstructorCandidate winnerCandidate)
        {
            if (winnerCandidate != null)
                return winnerPoints < candidatePoints;
            return true;
        }
        private static bool BestPossibleScore(ConstructorCandidate candidate, int candidatePoints)
        {
            return candidatePoints == candidate.Dependencies.Length * 100;
        }
        private bool CheckCtorCandidate(ConstructorCandidate candidate, CreationContext context, out int candidatePoints)
        {
            candidatePoints = 0;
            ConstructorDependencyModel[] dependencies = candidate.Dependencies;
            foreach (ConstructorDependencyModel constructorDependencyModel in dependencies) {
                if (CanSatisfyDependency(context, constructorDependencyModel))
                    candidatePoints += 100;
                else {
                    if (!constructorDependencyModel.HasDefaultValue) {
                        candidatePoints = 0;
                        return false;
                    }
                    candidatePoints++;
                }
            }
            return true;
        }
        protected virtual bool CanSatisfyDependency(CreationContext context, DependencyModel dependency)
        {
            return base.Kernel.Resolver.CanResolve(context, context.Handler, base.Model, dependency);
        }
        protected virtual object[] CreateConstructorArguments(ConstructorCandidate constructor, CreationContext context)
        {
            if (constructor == null)
                return null;
            int num = constructor.Dependencies.Length;
            if (num != 0) {
                object[] array = new object[num];
                try {
                    for (int i = 0; i < num; i++) {
                        array[i] = base.Kernel.Resolver.Resolve(context, context.Handler, base.Model, constructor.Dependencies[i]);
                    }
                    return array;
                } catch {
                    object[] array2 = array;
                    foreach (object instance in array2) {
                        base.Kernel.ReleaseComponent(instance);
                    }
                    throw;
                }
            }
            return null;
        }
        protected virtual void SetUpProperties(object instance, CreationContext context)
        {
            instance = ProxyUtil.GetUnproxiedInstance(instance);
            IDependencyResolver resolver = base.Kernel.Resolver;
            foreach (PropertySet property in base.Model.Properties) {
                object obj = ObtainPropertyValue(context, property, resolver);
                if (obj != null) {
                    MethodInfo setMethod = property.Property.GetSetMethod();
                    try {
                        setMethod.Invoke(instance, new object[1] {
                            obj
                        });
                    } catch (Exception innerException) {
                        throw new ComponentActivatorException(string.Format("Error setting property {1}.{0} in component {2}. See inner exception for more information.{4}If you don't want Windsor to set this property you can do it by either decorating it with {3} or via registration API.{4}Alternatively consider making the setter non-public.", property.Property.Name, instance.GetType().get_Name(), base.Model.Name, typeof(DoNotWireAttribute).get_Name(), Environment.NewLine), innerException, base.Model);
                    }
                }
            }
        }
        private object ObtainPropertyValue(CreationContext context, PropertySet property, IDependencyResolver resolver)
        {
            if (!property.Dependency.IsOptional || resolver.CanResolve(context, context.Handler, base.Model, property.Dependency))
                try {
                    return resolver.Resolve(context, context.Handler, base.Model, property.Dependency);
                } catch (Exception exception) {
                    if (!property.Dependency.IsOptional)
                        throw;
                    base.Kernel.Logger.Warn($"""{property.Dependency}""{base.Model.Name}""", exception);
                }
            return null;
        }
    }
}