Ejemplo n.º 1
0
 private static object CreateInstance <TInterface>(ComponentData componentData, IRegistrationInfo registrationInfo, params object[] constructorParameters)
 {
     return(CreateInstance(typeof(TInterface), componentData, registrationInfo, constructorParameters));
 }
Ejemplo n.º 2
0
        //private static object CreateInstance(Type interfaceType, ComponentData componentData, IEnumerable<Type> interceptorCollection, params object[] constructorParameters) {
        private static object CreateInstance(Type interfaceType, ComponentData componentData, IRegistrationInfo registrationInfo, params object[] constructorParameters)
        {
            // Obtém o primeiro tipo concreto registrado para ser instanciado.
            Type concreteType = componentData.ConcreteType;

            // Obtém os construtores públicos da classe concreta.
            ConstructorInfo[] constructorInfoCollection = concreteType.GetConstructors();

            // Verifica se existe um construtor padrão (sem parâmetros).
            bool hasDefaultContructor = constructorInfoCollection.Any(p => p.GetParameters().Length == 0);

            List <object> interceptors = new List <object>();

            if (registrationInfo != null && registrationInfo.InterceptorCollection.Any() == true)
            {
                foreach (Type interceptor in registrationInfo.InterceptorCollection)
                {
                    // Cria uma instancia do interceptor.
                    object interceptorInstance = Activator.CreateInstance(interceptor);

                    interceptors.Add(interceptorInstance);
                }
            }

            // Caso exista um construtor padrão e nenhum parâmetro tenha sido especificado, cria a instancia.
            if (hasDefaultContructor == true && constructorParameters.Length == 0)
            {
                // Cria e retorna uma nova instancia do tipo concreto com o construtor padrão.
                object instance = CreateInstance(registrationInfo, concreteType);

                // Caso algum interceptor tenha sido especificado, utiliza um proxy.
                return((registrationInfo.InterceptorCollection.Any() == false) ? instance : DynamicProxy.NewInstance(instance, interceptors.OfType <IInterceptor>().ToArray()));
            }

            // Caso não exista um construtor padrão, ou algum parâmetro tenha sido especificado.
            if (constructorParameters.Length > 0)
            {
                // Armazena a lista de tipos dos parâmetros do construtor.
                IEnumerable <Type> constructorParameterTypeCollection = constructorParameters.Select(p => p.GetType());

                // Analisa todos os construtores disponíveis.
                foreach (ConstructorInfo constructorInfo in constructorInfoCollection)
                {
                    // Obtém os parâmetros do construtor.
                    ParameterInfo[] parameterInfoCollection = constructorInfo.GetParameters();

                    // Caso o construtor não possua a mesma quantidade de parâmetros que foram informados, passa para o próximo construtor.
                    if (constructorParameterTypeCollection.Count() != parameterInfoCollection.Count())
                    {
                        continue;
                    }

                    // Obtém a lista de tipos dos parâmetros.
                    IEnumerable <Type> parameterTypeCollection = parameterInfoCollection.Select(p => p.ParameterType);

                    IList <Type> matchedParameterList = new List <Type>();

                    int parameterCounter = 0;

                    // Percorre a lista de parâmetros encontrados no construtor.
                    foreach (Type parameterType in parameterTypeCollection)
                    {
                        // Percorre a lista de parâmetros informados para instanciar o tipo.
                        do
                        {
                            Type constructorParameterType = constructorParameterTypeCollection.ElementAt(parameterCounter);

                            parameterCounter++;

                            if (constructorParameterType == parameterType || (parameterType.IsInterface && parameterType.IsAssignableFrom(constructorParameterType) == true) || constructorParameterType.BaseType == parameterType)
                            {
                                matchedParameterList.Add(constructorParameterType);
                                break;
                            }
                        } while (parameterCounter < constructorParameterTypeCollection.Count());
                    }

                    // Caso as assinaturas dos parâmetros e do construtor sejam identicas, utiliza o construtor atual.
                    if (matchedParameterList.Count == parameterTypeCollection.Count())
                    {
                        object instance = CreateInstance(registrationInfo, concreteType, constructorParameters);

                        // Caso algum interceptor tenha sido especificado, utiliza um proxy.
                        return((registrationInfo.InterceptorCollection.Any() == false) ? instance : DynamicProxy.NewInstance(instance, interceptors.OfType <IInterceptor>().ToArray()));
                    }
                }
            }

            IList <object> parameters = new List <object>();

            // Analisa todos os construtores disponíveis.
            foreach (ConstructorInfo constructorInfo in constructorInfoCollection)
            {
                // Obtém os parâmetros do construtor.
                ParameterInfo[] parameterInfoCollection = constructorInfo.GetParameters();

                // Verifica cada parâmetro do construtor.
                foreach (ParameterInfo parameterInfo in parameterInfoCollection)
                {
                    Type parameterType = parameterInfo.ParameterType;

                    // Verifica se não é um tipo base do .NET.
                    if (parameterType.FullName.StartsWith("System.") == false)
                    {
                        // Tenta localizar alguma interface registrada que seja do mesmo tipo do construtor.
                        IRegistrationInfo parameterRegistrationInfo = RegistrationInfoCollection.FirstOrDefault(p => p.InterfaceType.IsAssignableFrom(parameterType) == true);

                        // Caso nenhum tipo tenha sido encontrado, passa para o próximo parâmetro.
                        if (parameterRegistrationInfo == null)
                        {
                            continue;
                        }

                        ComponentData dependencyData = parameterRegistrationInfo.ComponentDataCollection.FirstOrDefault(p => p.ConcreteType != null && (p.ConcreteType == parameterType || parameterType.IsAssignableFrom(p.ConcreteType)));

                        if (dependencyData == null)
                        {
                            continue;
                        }

                        // Adiciona uma instancia do tipo encontrado na lista de parâmetros do construtor.
                        parameters.Add(CreateInstance(interfaceType, dependencyData, registrationInfo));
                    }
                }

                // Verifica se a quantidade de parâmetros esta de acordo com a quantidade de objetos disponíveis.
                if (parameters.Count == parameterInfoCollection.Length)
                {
                    object instance = CreateInstance(registrationInfo, concreteType, parameters.ToArray());

                    // Caso algum interceptor tenha sido especificado, utiliza um proxy.
                    return((registrationInfo.InterceptorCollection.Any() == false) ? instance : DynamicProxy.NewInstance(instance, interceptors.OfType <IInterceptor>().ToArray()));
                }
            }

            throw new InvalidOperationException("Could not find any constructor matching the specified parameters.");
        }
Ejemplo n.º 3
0
        private static object Resolve(Type interfaceType, string name, params object[] constructorParameters)
        {
            // Obtém a informação do registro de dependencias.
            IRegistrationInfo registrationInfo = RegistrationInfoCollection.FirstOrDefault(p => p.InterfaceType == interfaceType);

            // Verifica se existe uma mapeamento para a interface.
            if (registrationInfo == null)
            {
                throw new InvalidOperationException(string.Format("The interface type {0} is not registered.", interfaceType.FullName));
            }

            // Obtém as informações do primeiro tipo concreto registrado, que será instanciado.
            ComponentData componentData = null;

            // Verifica se foi especificado o nome do tipo a ser retornado.
            if (string.IsNullOrWhiteSpace(name) == true)
            {
                componentData = registrationInfo.ComponentDataCollection.OrderByDescending(p => p.IsDefault == true).FirstOrDefault();
            }
            else
            {
                componentData = registrationInfo.ComponentDataCollection.FirstOrDefault(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
            }

            // Verifica se alguma classe concreta foi encontrada para a interface.
            if (componentData == null)
            {
                throw new InvalidOperationException(string.Format("The interface type {0} does not have any associated concrete types.", interfaceType.FullName));
            }

            // Verifica se o tipo solicitado deve ser tratado como singleton.
            if (componentData.IsSingleton == true)
            {
                // Verifica se o tipo existe no dicionário de objetos instanciados.
                if (SingletonInstanceDictionary.ContainsKey(componentData.Name) == true)
                {
                    // Retorna o objeto já existente.
                    return(SingletonInstanceDictionary[componentData.Name]);
                }
            }

            // Obtém a instancia previamente definida pelo.
            object returnInstance = componentData.Instance;

            // Caso não exista uma instancia pré-definida, cria uma nova.
            if (componentData.Instance == null)
            {
                // Cria uma nova instancia.
                //returnInstance = CreateInstance(interfaceType, componentData, registrationInfo.InterceptorCollection, constructorParameters);
                returnInstance = CreateInstance(interfaceType, componentData, registrationInfo, constructorParameters);

                // Verifica se as propriedades desta classe que estejam registradas no container de injeção de dependência, devem ser instanciadas.
                if (registrationInfo.ResolveDependencies == true)
                {
                    // Obtém todas as propriedades que não sejam de sistema.
                    IEnumerable <PropertyInfo> propertyInfoCollection = interfaceType.GetProperties().Where(p => p.PropertyType.FullName.Equals("System") == false && p.CanWrite == true);

                    foreach (PropertyInfo propertyInfo in propertyInfoCollection)
                    {
                        Type propertyInterfaceType = (propertyInfo.PropertyType.IsInterface == true) ? propertyInfo.PropertyType : propertyInfo.PropertyType.GetInterface(string.Format("I{0}", propertyInfo.Name));

                        // Verifica se existe um registro para a interface da propriedade.
                        if (RegistrationInfoCollection.Any(p => p.InterfaceType == propertyInterfaceType) == false)
                        {
                            continue;
                        }

                        // Obtém uma instancia para o tipo da propriedade.
                        object propertyInstance = Resolve(propertyInterfaceType);

                        // Caso não tenha sido possível obter uma instancia, passa para a próxima propriedade.
                        if (propertyInstance == null)
                        {
                            continue;
                        }

                        // Define o valor da propriedade na instancia a ser retornada.
                        propertyInfo.SetValue(returnInstance, propertyInstance);
                    }
                }
            }

            // Caso o tipo deva ser tratado como singleton, adiciona a instancia recém criada no dicionário de objetos instanciados.
            if (componentData.IsSingleton == true && SingletonInstanceDictionary.ContainsKey(componentData.Name) == false)
            {
                SingletonInstanceDictionary.Add(componentData.Name, returnInstance);
            }

            return(returnInstance);
        }