Exemplo n.º 1
0
        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);
        }