예제 #1
0
        private void BuildInjectionPlan(INode n, IDictionary <INode, InjectionPlan> memo)
        {
            if (memo.ContainsKey(n))
            {
                InjectionPlan p = null;
                memo.TryGetValue(n, out p);
                if (BUILDING == p)
                {
                    StringBuilder loopyList = new StringBuilder("[");
                    foreach (INode node in memo.Keys)
                    {
                        InjectionPlan p1 = null;
                        memo.TryGetValue(node, out p1);
                        if (p1 == BUILDING)
                        {
                            loopyList.Append(" " + node.GetFullName());
                        }
                    }
                    loopyList.Append(" ]");
                    throw new ClassHierarchyException("Detected loopy constructor involving "
                                                      + loopyList.ToString());
                }
                else
                {
                    return;
                }
            }
            memo.Add(n, BUILDING);
            InjectionPlan ip = null;

            if (n is INamedParameterNode)
            {
                INamedParameterNode np = (INamedParameterNode)n;
                object boundInstance   = ParseBoundNamedParameter(np);
                object defaultInstance = this.classHierarchy.ParseDefaultValue(np);
                object instance        = boundInstance != null ? boundInstance : defaultInstance;

                if (instance is INode)
                {
                    BuildInjectionPlan((INode)instance, memo);
                    InjectionPlan sp = null;
                    memo.TryGetValue((INode)instance, out sp);
                    if (sp != null)
                    {
                        ip = new Subplan(n, 0, new InjectionPlan[] { sp });
                    }
                }
                else if (instance is ISet <object> )
                {
                    ISet <object>        entries = (ISet <object>)instance;
                    ISet <InjectionPlan> plans   = new MonotonicSet <InjectionPlan>();
                    foreach (object entry in entries)
                    {
                        if (entry is IClassNode)
                        {
                            BuildInjectionPlan((IClassNode)entry, memo);
                            InjectionPlan p2 = null;
                            memo.TryGetValue((INode)entry, out p2);
                            if (p2 != null)
                            {
                                plans.Add(p2);
                            }
                        }
                        else
                        {
                            plans.Add(new CsInstance(n, entry));
                        }
                    }
                    ip = new SetInjectionPlan(n, plans);
                }
                else
                {
                    ip = new CsInstance(np, instance);
                }
            }
            else if (n is IClassNode)
            {
                IClassNode cn = (IClassNode)n;

                // Any (or all) of the next four values might be null; that's fine.
                object     cached      = GetCachedInstance(cn);
                IClassNode boundImpl   = this.configuration.GetBoundImplementation(cn);
                IClassNode defaultImpl = ParseDefaultImplementation(cn);
                IClassNode ec          = this.configuration.GetBoundConstructor(cn);

                ip = BuildClassNodeInjectionPlan(cn, cached, ec, boundImpl, defaultImpl, memo);
            }
            else if (n is IPackageNode)
            {
                throw new ArgumentException(
                          "Request to instantiate Java package as object");
            }
            else
            {
                throw new IllegalStateException(
                          "Type hierarchy contained unknown node type!:" + n);
            }
            memo[n] = ip;
        }
예제 #2
0
        public object InjectFromPlan(InjectionPlan plan)
        {
            if (!plan.IsFeasible())
            {
                throw new InjectionException("Cannot inject " + plan.GetNode().GetFullName() + ": "
                                             + plan.ToCantInjectString());
            }
            if (plan.IsAmbiguous())
            {
                throw new InjectionException("Cannot inject " + plan.GetNode().GetFullName() + " "
                                             + plan.ToCantInjectString());
            }

            if (plan is InjectionFuturePlan)
            {
                InjectionFuturePlan fut = (InjectionFuturePlan)plan;
                string key = fut.GetNode().GetFullName();
                try
                {
                    //we will see if we need to introduce T to replace object
                    InjectionFuture ret = new InjectionFuture(this, classHierarchy.ClassForName(fut.GetNode().GetFullName()));
                    pendingFutures.Add(ret);
                    return(ret);
                }
                catch (TypeLoadException e)
                {
                    throw new InjectionException("Could not get class for " + key);
                }
            }
            else if (plan.GetNode() is IClassNode && null != GetCachedInstance((IClassNode)plan.GetNode()))
            {
                return(GetCachedInstance((IClassNode)plan.GetNode()));
            }
            else if (plan is CsInstance)
            {
                // TODO: Must be named parameter node.  Check.
                //      throw new IllegalStateException("Instance from plan not in Injector's set of instances?!?");
                return(((CsInstance)plan).instance);
            }
            else if (plan is Constructor)
            {
                Constructor     constructor = (Constructor)plan;
                object[]        args        = new object[constructor.GetArgs().Length];
                InjectionPlan[] argPlans    = constructor.GetArgs();

                for (int i = 0; i < argPlans.Length; i++)
                {
                    args[i] = InjectFromPlan(argPlans[i]);
                }

                try
                {
                    concurrentModificationGuard = true;
                    object ret;
                    try
                    {
                        IConstructorDef def = (IConstructorDef)constructor.GetConstructorDef();
                        ConstructorInfo c   = GetConstructor(def);

                        if (aspect != null)
                        {
                            ret = aspect.Inject(def, c, args);
                        }
                        else
                        {
                            ret = c.Invoke(args);
                        }
                    }
                    catch (ArgumentException e)
                    {
                        StringBuilder sb = new StringBuilder("Internal Tang error?  Could not call constructor " + constructor.GetConstructorDef() + " with arguments [");
                        foreach (Object o in args)
                        {
                            sb.Append("\n\t" + o);
                        }
                        sb.Append("]");
                        throw new IllegalStateException(sb.ToString(), e);
                    }
                    if (ret is IExternalConstructor)
                    {
                        ret = ((IExternalConstructor)ret).NewInstance();
                    }
                    instances.Add(constructor.GetNode(), ret);
                    return(ret);
                }
                catch (Exception e)
                {
                    throw new InjectionException("Could not invoke constructor: " + plan, e);  //check what exception might be got and refine it
                } finally
                {
                    concurrentModificationGuard = false;
                }
            }
            else if (plan is Subplan)
            {
                Subplan ambiguous = (Subplan)plan;
                return(InjectFromPlan(ambiguous.GetDelegatedPlan()));
            }
            else if (plan is SetInjectionPlan)
            {
                SetInjectionPlan setPlan = (SetInjectionPlan)plan;
                ISet <object>    ret     = new MonotonicSet <object>();
                foreach (InjectionPlan subplan in setPlan.GetEntryPlans())
                {
                    ret.Add(InjectFromPlan(subplan));
                }
                return(ret);
            }
            else
            {
                throw new IllegalStateException("Unknown plan type: " + plan);
            }
        }
예제 #3
0
        private void BuildInjectionPlan(INode n, IDictionary<INode, InjectionPlan> memo)
        {
            if (memo.ContainsKey(n))
             {
                InjectionPlan p = null;
                memo.TryGetValue(n, out p);
                if (BUILDING == p)
                {
                    StringBuilder loopyList = new StringBuilder("[");
                    foreach (INode node in memo.Keys)
                    {
                        InjectionPlan p1 = null;
                        memo.TryGetValue(node, out p1);
                        if(p1 == BUILDING)
                        {
                            loopyList.Append(" " + node.GetFullName());
                        }
                    }
                    loopyList.Append(" ]");
                    throw new ClassHierarchyException("Detected loopy constructor involving "
                        + loopyList.ToString());
                }
                else
                {
                    return;
                }
            }
            memo.Add(n, BUILDING);
            InjectionPlan ip = null;
            if (n is INamedParameterNode)
            {
                INamedParameterNode np = (INamedParameterNode)n;
                object boundInstance = ParseBoundNamedParameter(np);
                object defaultInstance = this.classHierarchy.ParseDefaultValue(np);
                object instance = boundInstance != null ? boundInstance : defaultInstance;

                if (instance is INode)
                {
                    BuildInjectionPlan((INode)instance, memo);
                    InjectionPlan sp = null;
                    memo.TryGetValue((INode)instance, out sp);
                    if (sp != null)
                    {
                        ip = new Subplan(n, 0, new InjectionPlan[] {sp});
                    }
                }
                else if(instance is ISet<object>)
                {
                    ISet<object> entries = (ISet<object>) instance;
                    ISet<InjectionPlan> plans = new MonotonicSet<InjectionPlan>();
                    foreach (object entry in entries)
                    {
                        if(entry is IClassNode)
                        {
                            BuildInjectionPlan((IClassNode)entry, memo);
                            InjectionPlan p2 = null;
                            memo.TryGetValue((INode)entry, out p2);
                            if (p2 != null)
                            {
                                plans.Add(p2);
                            }
                        }
                        else
                        {
                            plans.Add(new CsInstance(n, entry));
                        }

                    }
                    ip = new SetInjectionPlan(n, plans);
                }
                else
                {
                    ip = new CsInstance(np, instance);
                }

            }
            else if (n is IClassNode)
            {
                IClassNode cn = (IClassNode) n;

                // Any (or all) of the next four values might be null; that's fine.
                object cached = GetCachedInstance(cn);
                IClassNode boundImpl = this.configuration.GetBoundImplementation(cn);
                IClassNode defaultImpl = ParseDefaultImplementation(cn);
                IClassNode ec = this.configuration.GetBoundConstructor(cn);

                ip = BuildClassNodeInjectionPlan(cn, cached, ec, boundImpl, defaultImpl, memo);
            } else if (n is IPackageNode)
            {
                throw new ArgumentException(
                    "Request to instantiate Java package as object");
            } else
            {
                throw new IllegalStateException(
                    "Type hierarchy contained unknown node type!:" + n);
            }
            memo[n] = ip;
        }