using System; using System.Collections.Generic; using System.Reflection; namespace Wayne.Lib { public static class ServiceActivator { public static T Create(IServiceLocator serviceLocator, params object[] additionalParameter) where T : class { return (T)CreateInstance(string.Empty, typeof(T), serviceLocator, additionalParameter); } public static T Create(string serviceId, IServiceLocator serviceLocator, params object[] additionalParameter) where T : class { return (T)CreateInstance(serviceId, typeof(T), serviceLocator, additionalParameter); } private static object CreateInstance(string servicId, Type typeToInstantiate, IServiceLocator serviceLocator, params object[] additionalParameter) { List explaination = new List(); object result = TryCreate(typeToInstantiate, serviceLocator, servicId, explaination, additionalParameter); if (result == null) throw new ServiceContainerException(typeToInstantiate, string.Format("Could not create object of type {0} \r\n {1}", typeToInstantiate, string.Join("\r\n", explaination.ToArray()))); return result; } private static object TryCreate(Type typeToCreate, IServiceLocator serviceLocator, string serviceId, List explaination, params object[] additionalObjects) { var constructors = typeToCreate.GetConstructors(); Array.Reverse(constructors); var parameters = new List(); ConstructorInfo foundConstructor = null; foreach (ConstructorInfo constructor in constructors) { var parameterInfos = constructor.GetParameters(); parameters.Clear(); foreach (var parameterInfo in parameterInfos) { //Check for additionalObjectMatch first! int firstMatchingParameterObjectIndex = -1; for (int index = 0; index < additionalObjects.Length; index++) { object additionalObject = additionalObjects[index]; if (parameterInfo.ParameterType.IsInstanceOfType(additionalObject)) { firstMatchingParameterObjectIndex = index; break; } } if (firstMatchingParameterObjectIndex >= 0) { parameters.Add(additionalObjects[firstMatchingParameterObjectIndex]); } else { var dependency = serviceLocator.TryGetService(parameterInfo.ParameterType, serviceId); if (dependency != null) { parameters.Add(dependency); } else { explaination.Add(string.Format("Could not resolve parameter {0} of type {1}", parameterInfo.Name, parameterInfo.ParameterType)); } } } if (parameters.Count == parameterInfos.Length) { foundConstructor = constructor; break; } } if (foundConstructor != null) { var stateObject = foundConstructor.Invoke(parameters.ToArray()); return stateObject; } return null; } } }