private static object CreateInstance <TInterface>(ComponentData componentData, IRegistrationInfo registrationInfo, params object[] constructorParameters) { return(CreateInstance(typeof(TInterface), componentData, registrationInfo, constructorParameters)); }
//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."); }
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); }