private String ShallowArgString(InjectionPlan arg) { if (arg is Constructor || arg is Subplan) { return(arg.GetType().Name + ": " + arg.GetNode().GetName()); } else { return(arg.ToShallowString()); } }
private object GetInstance(INode node) { InjectionPlan plan = (InjectionPlan)GetInjectionPlan(node); object u = InjectFromPlan(plan); while (pendingFutures.Count != 0) { IEnumerator <object> i = pendingFutures.GetEnumerator(); i.MoveNext(); IInjectionFuture <object> f = (IInjectionFuture <object>)i.Current; pendingFutures.Remove(f); f.Get(); } return(u); }
private InjectionPlan BuildClassNodeInjectionPlan(IClassNode cn, object cachedInstance, IClassNode externalConstructor, IClassNode boundImpl, IClassNode defaultImpl, IDictionary <INode, InjectionPlan> memo) { if (cachedInstance != null) { return(new CsInstance(cn, cachedInstance)); } else if (externalConstructor != null) { BuildInjectionPlan(externalConstructor, memo); InjectionPlan ip = null; memo.TryGetValue(externalConstructor, out ip); return(new Subplan(cn, 0, new InjectionPlan[] { ip })); } else if (boundImpl != null && !cn.Equals(boundImpl)) { // We need to delegate to boundImpl, so recurse. BuildInjectionPlan(boundImpl, memo); InjectionPlan ip = null; memo.TryGetValue(boundImpl, out ip); return(new Subplan(cn, 0, new InjectionPlan[] { ip })); } else if (defaultImpl != null && !cn.Equals(defaultImpl)) { BuildInjectionPlan(defaultImpl, memo); InjectionPlan ip = null; memo.TryGetValue(defaultImpl, out ip); return(new Subplan(cn, 0, new InjectionPlan[] { ip })); } else { // if we're here and there is a bound impl or a default impl, // then we're bound / defaulted to ourselves, so don't add // other impls to the list of things to consider. List <IClassNode> candidateImplementations = new List <IClassNode>(); candidateImplementations.Add(cn); List <InjectionPlan> sub_ips = FilterCandidateConstructors(candidateImplementations, memo); if (sub_ips.Count == 1) { return(WrapInjectionPlans(cn, sub_ips, false, -1)); } return(WrapInjectionPlans(cn, sub_ips, true, -1)); } }
public InjectionPlan GetInjectionPlan(INode n) { AssertNotConcurrent(); IDictionary <INode, InjectionPlan> memo = new Dictionary <INode, InjectionPlan>(); BuildInjectionPlan(n, memo); InjectionPlan p = null; memo.TryGetValue(n, out p); if (p != null) { return(p); } Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new InjectionException("Fail to get injection plan" + n), LOGGER); return(null);//this line shouild be not reached as Throw throws exception }
private void CreateInjectionPlanForCollectionElements <T>(INode n, IDictionary <INode, InjectionPlan> memo, ICollection <T> entries, ICollection <InjectionPlan> plans) { foreach (var 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)); } } }
public InjectionPlan[] GetPlans() { InjectionPlan[] copy = new InjectionPlan[alternatives.Length]; Array.Copy(alternatives, copy, alternatives.Length); // not sure if it does deep copy?? return(copy); }
public bool IsParameterSet(string name) { InjectionPlan p = GetInjectionPlan(classHierarchy.GetNode(name)); return(p.IsInjectable()); }
public object InjectFromPlan(InjectionPlan plan) { if (!plan.IsFeasible()) { var ex = new InjectionException("Cannot inject " + plan.GetNode().GetFullName() + ": " + plan.ToCantInjectString()); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER); } if (plan.IsAmbiguous()) { var ex = new InjectionException("Cannot inject " + plan.GetNode().GetFullName() + " " + plan.ToCantInjectString()); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER); } if (plan is InjectionFuturePlan) { InjectionFuturePlan fut = (InjectionFuturePlan)plan; INode node = fut.GetNode(); string key = node.GetFullName(); try { Type t = null; Type nodeType = classHierarchy.ClassForName(node.GetFullName()); if (node is IClassNode) { t = nodeType; } else if (node is INamedParameterNode) { var nn = (INamedParameterNode)node; t = classHierarchy.ClassForName(nn.GetFullArgName()); if (nn.IsSet()) { t = typeof(ISet <>).MakeGenericType(new Type[] { t }); } } else { var ex = new ApplicationException("Unexpected node type. Wanted ClassNode or NamedParameterNode. Got: " + node); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER); } //Java - InjectionFuture<?> ret = new InjectionFuture<>(this, javaNamespace.classForName(fut.getNode().getFullName())); //C# - InjectionFuture<object> ret = new InjectionFutureImpl<object>(this, classHierarchy.ClassForName(fut.GetNode().GetFullName())); //We cannot simply create an object from generic with object as <T> //typeof(InjectionFutureImpl<>).MakeGenericType(t) will get the InjectionFutureImpl generic Type with <T> as t //for ClassNode, t is the Type of the class, for NamedParamterNode, t is the Type of the argument //we then use reflection to invoke the constructor //To retain generic argument information?? Type injectionFuture = typeof(InjectionFutureImpl <>).MakeGenericType(t); var constructor = injectionFuture.GetConstructor(new Type[] { typeof(IInjector), typeof(Type) }); IInjectionFuture <object> ret = (IInjectionFuture <object>)constructor.Invoke(new object[] { this, nodeType }); pendingFutures.Add(ret); return(ret); } catch (TypeLoadException e) { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, LOGGER); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new InjectionException("Could not get class for " + key), LOGGER); } } 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 = null; 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) { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, LOGGER); 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("]"); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new IllegalStateException(sb.ToString(), e), LOGGER); } if (ret is IExternalConstructor <object> ) { ret = ((IExternalConstructor <object>)ret).NewInstance(); } instances.Add(constructor.GetNode(), ret); return(ret); } catch (TargetInvocationException e) { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, LOGGER); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new InjectionException("Could not invoke constructor: " + plan, e), LOGGER); } 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; INode n = setPlan.GetNode(); string typeOfSet = null; // TODO: This doesn't work for sets of generics (e.g., Set<Foo<int>> // because GetFullName and GetFullArgName strip generic info). if (n is INamedParameterNode) { INamedParameterNode np = (INamedParameterNode)n; typeOfSet = np.GetFullArgName(); } else if (n is IClassNode) { typeOfSet = n.GetFullName(); } else { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new ApplicationException("Unknown node type :" + n.ToString()), LOGGER); } Type t = classHierarchy.ClassForName(typeOfSet); // MakeGenericType(t = int: MonotonicHashSet<> -> MonotonicHashSet<int> // Get constructor: MonotonicHashSet<int> -> public MonotonicHashSet<int>() { ... } // Invoke: public MonotonicHashSet<int> -> new MonotonicHashSet<int>() object ret = typeof(MonotonicHashSet <>).MakeGenericType(t).GetConstructor(new Type[] { }).Invoke(new object[] { }); //(this, classHierarchy.ClassForName(fut.GetNode().GetFullName())); MethodInfo mf = ret.GetType().GetMethod("Add"); foreach (InjectionPlan subplan in setPlan.GetEntryPlans()) { // ret.Add(InjectFromPlan(subplan)); mf.Invoke(ret, new object[] { InjectFromPlan(subplan) }); } return(ret); } else if (plan is ListInjectionPlan) { ListInjectionPlan listPlan = (ListInjectionPlan)plan; INode n = listPlan.GetNode(); string typeOfList = null; if (n is INamedParameterNode) { INamedParameterNode np = (INamedParameterNode)n; typeOfList = np.GetFullArgName(); } else if (n is IClassNode) { typeOfList = n.GetFullName(); } else { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new ApplicationException("Unknown node type :" + n.ToString()), LOGGER); } Type t = classHierarchy.ClassForName(typeOfList); object ret = typeof(List <>).MakeGenericType(t).GetConstructor(new Type[] { }).Invoke(new object[] { }); MethodInfo mf = ret.GetType().GetMethod("Add"); foreach (InjectionPlan subplan in listPlan.GetEntryPlans()) { mf.Invoke(ret, new object[] { InjectFromPlan(subplan) }); } return(ret); } else { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new IllegalStateException("Unknown plan type: " + plan), LOGGER); } return(null); // should never reach here }
private List <InjectionPlan> FilterCandidateConstructors( List <IClassNode> candidateImplementations, IDictionary <INode, InjectionPlan> memo) { List <InjectionPlan> sub_ips = new List <InjectionPlan>(); #region each implementation foreach (IClassNode thisCN in candidateImplementations) { List <InjectionPlan> constructors = new List <InjectionPlan>(); List <IConstructorDef> constructorList = new List <IConstructorDef>(); if (null != this.configuration.GetLegacyConstructor(thisCN)) { constructorList.Add(this.configuration.GetLegacyConstructor(thisCN)); } foreach (var c in thisCN.GetInjectableConstructors()) { constructorList.Add(c); } #region each constructor foreach (IConstructorDef def in constructorList) { List <InjectionPlan> args = new List <InjectionPlan>(); IConstructorArg[] defArgs = def.GetArgs().ToArray <IConstructorArg>(); #region each argument foreach (IConstructorArg arg in defArgs) { if (!arg.IsInjectionFuture()) { try { INode argNode = this.classHierarchy.GetNode(arg.GetName()); BuildInjectionPlan(argNode, memo); InjectionPlan ip = null; memo.TryGetValue(argNode, out ip); args.Add(ip); } catch (NameResolutionException e) { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, LOGGER); var ex = new IllegalStateException("Detected unresolvable " + "constructor arg while building injection plan. " + "This should have been caught earlier!", e); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER); } } else { try { args.Add(new InjectionFuturePlan(this.classHierarchy.GetNode(arg.GetName()))); } catch (NameResolutionException e) { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, LOGGER); var ex = new IllegalStateException("Detected unresolvable " + "constructor arg while building injection plan. " + "This should have been caught earlier!", e); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER); } } } #endregion each argument Constructor constructor = new Constructor(thisCN, def, args.ToArray()); constructors.Add(constructor); } #endregion each constructor // The constructors are embedded in a lattice defined by // isMoreSpecificThan(). We want to see if, amongst the injectable // plans, there is a unique dominant plan, and select it. // First, compute the set of injectable plans. List <Int32> liveIndices = new List <Int32>(); for (int i = 0; i < constructors.Count; i++) { if (constructors[i].GetNumAlternatives() > 0) { liveIndices.Add(i); } } // Now, do an all-by-all comparison, removing indices that are dominated // by others. int k = -1; for (int i = 0; i < liveIndices.Count; i++) { for (int j = i + 1; j < liveIndices.Count; j++) { IConstructorDef ci = ((Constructor)constructors[(liveIndices[i])]).GetConstructorDef(); IConstructorDef cj = ((Constructor)constructors[(liveIndices[j])]).GetConstructorDef(); if (ci.IsMoreSpecificThan(cj)) //ci's arguments is a superset of cj's { k = i; } else if (cj.IsMoreSpecificThan(ci)) { k = j; } } } if (liveIndices.Count == 1) { k = 0; } if (constructors.Count > 0) { sub_ips.Add(WrapInjectionPlans(thisCN, constructors, false, k != -1 ? liveIndices[k] : -1)); } } #endregion each implementation return(sub_ips); }
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(" ]"); var ex = new ClassHierarchyException("Detected loopy constructor involving " + loopyList.ToString()); Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER); } 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; memo.TryGetValue((INode)instance, out sp); ip = new Subplan(n, 0, new InjectionPlan[] { sp }); } else if (instance is ISet <object> ) { ISet <object> entries = (ISet <object>)instance; ip = CreateSetInjectionPlan(n, memo, entries); } else if (instance is ISet <INode> ) { ISet <INode> entries = (ISet <INode>)instance; ip = CreateSetInjectionPlan(n, memo, entries); } else if (instance is IList <object> ) { IList <object> entries = (IList <object>)instance; ip = CreateListInjectionPlan(n, memo, entries); } else if (instance is IList <INode> ) { IList <INode> entries = (IList <INode>)instance; ip = CreateListInjectionPlan(n, memo, entries); } 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) { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new ArgumentException( "Request to instantiate Java package as object"), LOGGER); } else { Org.Apache.Reef.Utilities.Diagnostics.Exceptions.Throw(new IllegalStateException( "Type hierarchy contained unknown node type!:" + n), LOGGER); } memo[n] = ip; }