/// <summary> /// Initializes the object graph by building every object and resolving all dependencies. /// </summary> public static void BuildGraph() { // List of all objects we need to inject dependencies into. var InjectList = new List <object>(); // First we build every type we have registered but isn't yet built. // This allows us to run this after the content assembly has been loaded. foreach (KeyValuePair <Type, Type> currentType in ResolveTypes.Where(p => !Services.ContainsKey(p.Key))) { // Find a potential dupe by checking other registered types that have already been instantiated that have the same instance type. // Can't catch ourselves because we're not instantiated. // Ones that aren't yet instantiated are about to be and'll find us instead. KeyValuePair <Type, Type> DupeType = ResolveTypes.FirstOrDefault(p => Services.ContainsKey(p.Key) && p.Value == currentType.Value); // Interface key can't be null so since KeyValuePair<> is a struct, // this effectively checks whether we found something. if (DupeType.Key != null) { // We have something with the same instance type, use that. Services[currentType.Key] = Services[DupeType.Key]; continue; } try { var instance = Activator.CreateInstance(currentType.Value); Services[currentType.Key] = instance; InjectList.Add(instance); } catch (TargetInvocationException e) { throw new ImplementationConstructorException(currentType.Value, e.InnerException); } } // Graph built, go over ones that need injection. foreach (var Implementation in InjectList) { foreach (FieldInfo field in Implementation.GetType() .GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .Where(p => Attribute.GetCustomAttribute(p, typeof(DependencyAttribute)) != null)) { // Not using Resolve<T>() because we're literally building it right now. if (!Services.ContainsKey(field.FieldType)) { throw new UnregisteredDependencyException(Implementation.GetType(), field.FieldType, field.Name); } // Quick note: this DOES work with readonly fields, though it may be a CLR implementation detail. field.SetValue(Implementation, Services[field.FieldType]); } } foreach (IPostInjectInit InjectedItem in InjectList.OfType <IPostInjectInit>()) { InjectedItem.PostInject(); } }
/// <summary> /// Initializes the object graph by building every object and resolving all dependencies. /// </summary> /// <seealso cref="InjectDependencies(object)"/> public static void BuildGraph() { // List of all objects we need to inject dependencies into. var InjectList = new List <object>(); // First we build every type we have registered but isn't yet built. // This allows us to run this after the content assembly has been loaded. foreach (KeyValuePair <Type, Type> currentType in ResolveTypes.Where(p => !Services.ContainsKey(p.Key))) { // Find a potential dupe by checking other registered types that have already been instantiated that have the same instance type. // Can't catch ourselves because we're not instantiated. // Ones that aren't yet instantiated are about to be and'll find us instead. KeyValuePair <Type, Type> DupeType = ResolveTypes.FirstOrDefault(p => Services.ContainsKey(p.Key) && p.Value == currentType.Value); // Interface key can't be null so since KeyValuePair<> is a struct, // this effectively checks whether we found something. if (DupeType.Key != null) { // We have something with the same instance type, use that. Services[currentType.Key] = Services[DupeType.Key]; continue; } try { var instance = Activator.CreateInstance(currentType.Value); Services[currentType.Key] = instance; InjectList.Add(instance); } catch (TargetInvocationException e) { throw new ImplementationConstructorException(currentType.Value, e.InnerException); } } // Graph built, go over ones that need injection. foreach (var Implementation in InjectList) { InjectDependencies(Implementation); } foreach (IPostInjectInit InjectedItem in InjectList.OfType <IPostInjectInit>()) { InjectedItem.PostInject(); } }