private MethodInfoCache FindConstructorMethodRecursive(Type type) { MethodInfo constructorMethodInfo = null; MethodInfo[] allStaticMethods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); foreach (var info in allStaticMethods) { if (info.GetCustomAttributes(typeof(ConstructorAttribute), true).Length <= 0) { continue; } // Does it return an instance of itself? if (info.ReturnType == type) { constructorMethodInfo = info; break; } } if (constructorMethodInfo == null) { return(null); } ParameterInfo[] methodParameters = constructorMethodInfo.GetParameters(); object[] injectAttributes = constructorMethodInfo.GetCustomAttributes(typeof(InjectAttribute), true); InjectAttribute injectAttribute = null; if (injectAttributes.Length > 0) { injectAttribute = (InjectAttribute)injectAttributes[0]; } ParameterInfoCache[] parameters = GetParameterInfoCache(constructorMethodInfo.GetParameters()); var constructorMethodInfoCache = new MethodInfoCache(constructorMethodInfo, injectAttribute, parameters); return(constructorMethodInfoCache); }
protected virtual List <MethodInfoCache> FindMethodsRecursive(Type type, List <MethodInfoCache> methods = null) { if (methods == null) { methods = new List <MethodInfoCache>(); } var subMethods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (var info in subMethods) { if (info.IsSpecialName || !MightHaveInjectAttribute(info)) { continue; } object[] injectAttributes = info.GetCustomAttributes(typeof(InjectAttribute), true); if (injectAttributes.Length <= 0) { continue; } InjectAttribute injectAttribute = (InjectAttribute)injectAttributes[0]; MethodInfoCache methodInfoCache = new MethodInfoCache(info, injectAttribute, GetParameterInfoCache(info.GetParameters())); methods.Add(methodInfoCache); } if (IsRootType(type.BaseType)) { return(methods); } FindMethodsRecursive(type.BaseType, methods); return(methods); }
private void InjectMethod(IContainer container, IInjectContext parentContext, Type type, object obj, MethodInfoCache method) { ParameterInfoCache[] parameters = method.Parameters; if (parameters == null || parameters.Length == 0) { method.MethodInfo.Invoke(obj, null); return; } object[] paramObjects = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { ParameterInfoCache parameter = parameters[i]; ParameterInfo parameterInfo = parameter.ParameterInfo; // Can we resolve this? if (container.HasBindingFor(parameterInfo.ParameterType)) { // Prevent recursive / circular dependency... if (parameterInfo.ParameterType.IsAssignableFrom(type) || _currentlyResolvingTypes.Contains(parameterInfo.ParameterType)) { LogHandler?.Invoke("Injector: Circular dependency detected in Method {0}.{1}, parameter index: {2}", type, method.MethodInfo.Name, i); paramObjects[i] = null; } else { InjectContext injectContext = new InjectContext(container, method.DeclaringType, parentContext); Type parameterType = parameterInfo.ParameterType; object paramInstance = container.ResolveWithCategory(parameterType, parameter.InjectAttribute?.Category, injectContext); paramObjects[i] = paramInstance; } } else { LogHandler?.Invoke("Injector: {0} - Type is not bound in the container, assigning as null {1}, method {2}, parameter index: {2}", type, parameterInfo.ParameterType, method.MethodInfo.Name, i); paramObjects[i] = null; } } method.MethodInfo.Invoke(obj, paramObjects.ToArray()); }
public void Inject(object objValue, IInjectContext parentContext) { Type tType = objValue.GetType(); // Ensure cached reflection... PreInjectReflection(tType); _currentlyResolvingTypes.Add(tType); // Inject methods... for (int i = 0; i < _cachedMethods[tType].Count(); i++) { MethodInfoCache method = _cachedMethods[tType].ElementAt(i); InjectMethod(_container, parentContext, tType, objValue, method); } // Inject into Fields... for (int i = 0; i < _cachedFields[tType].Count(); i++) { MemberInfoCache memberCache = _cachedFields[tType].ElementAt(i); FieldInfo field = (FieldInfo)memberCache.MemberInfo; bool isCircularReference = false; if (field.FieldType.IsAssignableFrom(typeof(IContainer))) { field.SetValue(objValue, _container); continue; } foreach (Type type in _currentlyResolvingTypes) { if (field.FieldType.IsAssignableFrom(type)) { var binding = _container.GetBinding(field.FieldType, memberCache.InjectAttribute.Category); if (binding != null && binding.BindingType == BindingType.Transient) { isCircularReference = true; } } } if (isCircularReference) { LogHandler?.Invoke("Injector: Circular dependency detected in Field {0}.{1}", tType, field.Name); } else { InjectContext injectContext = new InjectContext(_container, memberCache.DeclaringType, parentContext); object fieldValue = _container.ResolveWithCategory(field.FieldType, memberCache.InjectAttribute.Category, injectContext); field.SetValue(objValue, fieldValue); } } // Inject into Properties... for (int i = 0; i < _cachedProperties[tType].Count(); i++) { MemberInfoCache memberCache = _cachedProperties[tType].ElementAt(i); PropertyInfo property = (PropertyInfo)memberCache.MemberInfo; bool isCircularReference = false; if (property.PropertyType.IsAssignableFrom(typeof(IContainer))) { property.SetValue(objValue, _container, null); continue; } foreach (Type type in _currentlyResolvingTypes) { if (property.PropertyType.IsAssignableFrom(type)) { var binding = _container.GetBinding(property.PropertyType, memberCache.InjectAttribute.Category); if (binding != null && binding.BindingType == BindingType.Transient) { isCircularReference = true; } } } if (isCircularReference) { LogHandler?.Invoke("Injector: Circular dependency detected in Property {0}.{1}", tType, property.Name); } else { InjectContext injectContext = new InjectContext(_container, memberCache.DeclaringType, parentContext); object propertyValue = _container.ResolveWithCategory(property.PropertyType, memberCache.InjectAttribute.Category, injectContext); property.SetValue(objValue, propertyValue, null); } } _currentlyResolvingTypes.Remove(tType); }
protected object ExecuteStaticMethodConstructor(IContainer container, IInjectContext parentContext, MethodInfoCache method, Type type, params object[] addDependencies) { ParameterInfoCache[] parameters = method.Parameters; if (parameters == null || parameters.Length == 0) { return(method.MethodInfo.Invoke(null, null)); } object[] paramObjects = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { ParameterInfoCache parameter = parameters[i]; ParameterInfo parameterInfo = parameter.ParameterInfo; // Can we resolve this? if (container.HasBindingFor(parameterInfo.ParameterType)) { bool isCircularDependency = false; foreach (var resolvingType in _currentlyResolvingTypes) { if (parameterInfo.ParameterType.IsAssignableFrom(resolvingType)) { isCircularDependency = true; } } // Prevent recursive / circular dependency... if (isCircularDependency) { LogHandler?.Invoke("Injector: Circular dependency detected in Method {0}.{1}, parameter index: {2}", type, method.MethodInfo.Name, i); paramObjects[i] = null; } else { InjectContext injectContext = new InjectContext(container, method.DeclaringType, parentContext); Type parameterType = parameterInfo.ParameterType; object paramInstance = container.ResolveWithCategory(parameterType, parameter.InjectAttribute?.Category, injectContext); paramObjects[i] = paramInstance; } } else { bool hasAdditionalDependency = false; // Check additional dependencies... foreach (object dependency in addDependencies) { if (parameterInfo.ParameterType.IsInstanceOfType(dependency)) { hasAdditionalDependency = true; paramObjects[i] = dependency; break; } } if (!hasAdditionalDependency) { LogHandler?.Invoke("Injector: {0} - Type is not bound in the container, assigning as null {1}, method {2}, parameter index: {2}", type, parameterInfo.ParameterType, method.MethodInfo.Name, i); paramObjects[i] = null; } } } // Invoke constructor... object instance = method.MethodInfo.Invoke(null, paramObjects); return(instance); }