private object Resolve(Type contract, string name, PropertiesTypeCondition propertiesCondition = PropertiesTypeCondition.Search)
        {
            var typesFound = from t in Types
                             where t.Key == contract
                             select t;
            var typeRegisters = typesFound as IList <TypeRegister> ?? typesFound.ToList();

            ValidateTypeRegistersAndPropertiesCondition(typeRegisters, propertiesCondition, contract);

            var typeRegistered = ValidateTotalTypesFound(typeRegisters, name);

            if (typeRegistered == null)
            {
                return(null);
            }

            var implementation = typeRegistered.Implementation;

            var constructor           = implementation.GetConstructors()[0];
            var constructorParameters = constructor.GetParameters();
            var propertiesParameters  = implementation.GetProperties();

            if (ValidateConstructorAndPropertiesParameters(constructorParameters, propertiesParameters))
            {
                if (ValidateInstance(typeRegistered, InstanceTypeCondition.Share))
                {
                    typeRegistered.Instance = Activator.CreateInstance(implementation);
                }
                return(typeRegistered.Instance ?? Activator.CreateInstance(implementation));
            }

            var parameters = new List <object>(constructorParameters.Length);

            PopulateInstanceParameters(parameters, typeRegistered, constructorParameters);

            if (ValidateInstance(typeRegistered, InstanceTypeCondition.Share))
            {
                typeRegistered.Instance = constructor.Invoke(parameters.ToArray());
            }

            var newInstance = typeRegistered.Instance ?? constructor.Invoke(parameters.ToArray());

            if (typeRegistered.PropertiesCondition == PropertiesTypeCondition.DisposeAll)
            {
                return(newInstance);
            }

            foreach (var propertyInfo in propertiesParameters)
            {
                if (propertyInfo.PropertyType.IsInterface)
                {
                    var value = Resolve(propertyInfo.PropertyType, propertyInfo.Name, propertiesCondition);
                    if (value != null)
                    {
                        propertyInfo.SetValue(newInstance, value, null);
                    }
                }
            }
            return(newInstance);
        }
        /// <summary>
        /// Registrar un objeto en un contenedor IoC
        /// </summary>
        /// <typeparam name="TContract">Representa la implementacion del contrato</typeparam>
        /// <typeparam name="TImplementation">Representa the implementation of the contract</typeparam>
        /// <param name="name"></param>
        /// <param name="instance">Establecer una instancia de una aplicación ya creada</param>
        /// <param name="propertiesCondition"></param>
        /// <param name="instanceCondition">Share = Usa la misma instancia, NonShare = Crear una nueva instancia cada vez que</param>
        public void Register <TContract, TImplementation>(string name, TImplementation instance, PropertiesTypeCondition propertiesCondition, InstanceTypeCondition instanceCondition)
        {
            var typeFound = from t in Types
                            where t.Key == typeof(TContract) && t.Implementation == typeof(TImplementation)
                            select t;
            var typeRegisters = typeFound as TypeRegister[] ?? typeFound.ToArray();

            if (!typeRegisters.Any())
            {
                Types.Add(new TypeRegister {
                    Key = typeof(TContract), Implementation = typeof(TImplementation), Name = name, Instance = instance, PropertiesCondition = propertiesCondition, InstanceCondition = instanceCondition
                });
            }
            else
            {
                typeRegisters.First().Instance = instance;
            }
        }
        /// <summary>
        /// Registrar un objeto en un contenedor IoC
        /// </summary>
        /// <typeparam name="TContract">Represent an interface</typeparam>
        /// <typeparam name="TImplementation">Representa la implementacion del contrato</typeparam>
        /// <param name="name"></param>
        /// <param name="instance">Establecer una instancia de una aplicación ya creada</param>
        /// <param name="propertiesCondition"></param>
        public void Register <TContract, TImplementation>(string name, TImplementation instance, PropertiesTypeCondition propertiesCondition)
        {
            var typeFound = from t in Types
                            where t.Key == typeof(TContract) && t.Implementation == typeof(TImplementation)
                            select t;

            if (!typeFound.Any())
            {
                Types.Add(new TypeRegister {
                    Key = typeof(TContract), Implementation = typeof(TImplementation), Name = name, Instance = instance, PropertiesCondition = propertiesCondition
                });
            }
        }
 private static void ValidateTypeRegistersAndPropertiesCondition(IList <TypeRegister> typeRegisters, PropertiesTypeCondition propertiesCondition, Type contract)
 {
     if (!typeRegisters.Any() && propertiesCondition != PropertiesTypeCondition.AllowNull)
     {
         throw new ArgumentNullException($"Type {contract.Name} is not registered ");
     }
 }