public async Task <INode> ResolveToNodeAsync(IPlan plan) { #endif if (!plan.Planned) { return((INode)plan); } foreach (var dependent in plan.DependentOnPlans) { if (dependent.Discarded) { throw new ActivationException("This plan was dependent on plan '" + dependent.FullName + "' / '" + dependent.PlanName + "', but that plan has since been discarded. Re-create this plan to resolve it.", plan); } else if (dependent.Planned) { throw new ActivationException("This plan is dependent on plan '" + dependent.FullName + "' / '" + dependent.PlanName + "', but that plan is not resolved yet.", plan); } } foreach (var node in plan.PlannedCreatedNodes) { var toCreate = (DefaultNode)node; if (toCreate.Planned && toCreate.UntypedValue != null) { // This is a factory. toCreate.Planned = false; } else if (toCreate.Planned && toCreate.PlannedMethod != null) { toCreate.Planned = false; _hierarchy.ChangeObjectOnNode( toCreate, toCreate.PlannedMethod(new DefaultContext(this, ((DefaultNode)node).Parent, node))); } else if (toCreate.Planned && toCreate.Deferred) { // Remove this deferred node from the tree, because the // resolved target node will be used by ResolveArgument // to provide any parameter values as needed. _hierarchy.RemoveNode(toCreate); } else if (toCreate.Planned) { var parameters = new List <object>(); foreach (var argument in toCreate.PlannedConstructorArguments) { #if !PLATFORM_UNITY parameters.Add(await ResolveArgument(toCreate, argument)); #else parameters.Add(ResolveArgument(toCreate, argument)); #endif } try { // Create the uninitialized object so that node lookups work before the constructors // have finished being called. toCreate.UntypedValue = FormatterServices.GetUninitializedObject(toCreate.Type); _hierarchy.ChangeObjectOnNode(toCreate, toCreate.UntypedValue); // If the object being created has [InjectFieldsForBaseObjectInProtectedConstructorAttribute] // on any of it's base classes, inject them now. var cls = toCreate.UntypedValue.GetType().BaseType; while (cls != null) { var wantsFieldsInjected = cls.GetCustomAttributes(false).Any( x => x is InjectFieldsForBaseObjectInProtectedConstructorAttribute); if (wantsFieldsInjected) { var nodeField = cls.GetField("_node", BindingFlags.NonPublic | BindingFlags.Instance); var hierarchyField = cls.GetField("_hierarchy", BindingFlags.NonPublic | BindingFlags.Instance); if (nodeField.FieldType == typeof(INode)) { nodeField.SetValue(toCreate.UntypedValue, toCreate); } if (hierarchyField.FieldType == typeof(IHierarchy)) { hierarchyField.SetValue(toCreate.UntypedValue, _hierarchy); } } cls = cls.BaseType; } toCreate.PlannedConstructor.Invoke(toCreate.UntypedValue, parameters.ToArray()); var asyncConstructable = toCreate.UntypedValue as IAsynchronouslyConstructable; if (asyncConstructable != null) { await asyncConstructable.ConstructAsync(); } } catch (TargetInvocationException ex) { #if !PLATFORM_UNITY ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); #else throw ex.InnerException; #endif } toCreate.Planned = false; } } if (plan.DiscardOnResolve.Count > 0) { foreach (var child in plan.DiscardOnResolve.ToList()) { _hierarchy.RemoveNode((INode)child); } } return((INode)plan); }