public virtual int moreSpecific(Twonk other) { if (other.vec.Length != vec.Length) return - 1; bool low = false; bool high = false; for (int i = 0; i < vec.Length; i++) { if (vec[i] > other.vec[i]) { high = true; } else if (vec[i] < other.vec[i]) { low = true; } } /* * this is a 'crossing' - meaning that * we saw the parameter 'slopes' cross * this means ambiguity */ if (high && low) return 0; /* * we saw that all args were 'high', meaning * that the other method is more specific so * we are less */ if (high && !low) return - 1; /* * we saw that all points were lower, therefore * we are more specific */ if (!high && low) return 1; /* * the remainder, neither high or low * means we are the same. This really can't * happen, as it implies the same args, right? */ return 1; }
public int moreSpecific(Twonk other) { int result; if (other.vec.Length != this.vec.Length) { result = -1; } else { bool flag = false; bool flag2 = false; for (int i = 0; i < this.vec.Length; i++) { if (this.vec[i] > other.vec[i]) { flag2 = true; } else if (this.vec[i] < other.vec[i]) { flag = true; } } if (flag2 && flag) { result = 0; } else if (flag2 && !flag) { result = -1; } else if (!flag2 && flag) { result = 1; } else { result = 1; } } return(result); }
public virtual int moreSpecific(Twonk other) { if (other.vec.Length != vec.Length) { return(-1); } bool low = false; bool high = false; for (int i = 0; i < vec.Length; i++) { if (vec[i] > other.vec[i]) { high = true; } else if (vec[i] < other.vec[i]) { low = true; } } /* * this is a 'crossing' - meaning that * we saw the parameter 'slopes' cross * this means ambiguity */ if (high && low) { return(0); } /* * we saw that all args were 'high', meaning * that the other method is more specific so * we are less */ if (high && !low) { return(-1); } /* * we saw that all points were lower, therefore * we are more specific */ if (!high && low) { return(1); } /* * the remainder, neither high or low * means we are the same. This really can't * happen, as it implies the same args, right? */ return(1); }
/// <summary> Calculates the distance, expressed as a vector of inheritance /// steps, between the calling args and the method args. /// There still is an issue re interfaces... /// </summary> private Twonk calcDistance(System.Object[] set , System.Type[] base_Renamed) { if (set.Length != base_Renamed.Length) return null; Twonk twonk = new Twonk(set.Length); int distance = 0; for (int i = 0; i < set.Length; i++) { /* * can I get from here to there? */ System.Type setclass = set [i].GetType(); if (!base_Renamed[i].IsAssignableFrom(set [i].GetType())) return null; /* * ok, I can. How many steps? */ System.Type c = setclass; while (c != null) { /* * is this a valid step? */ if (!base_Renamed[i].IsAssignableFrom(c)) { /* * it stopped being assignable - therefore we are looking at * an interface as our target, so move back one step * from the distance as the stop wasn't valid */ break; } if (base_Renamed[i].Equals(c)) { /* * we are equal, so no need to move forward */ break; } c = c.BaseType; twonk.distance++; twonk.vec[i]++; } } return twonk; }
/// <summary> <p> /// Find a method. Attempts to find the /// most appropriate method using the /// sense of 'specificity'. /// </p> /// /// <p> /// This turns out to be a relatively rare case /// where this is needed - however, functionality /// like this is needed. This may not be the /// optimum approach, but it works. /// </p> /// </summary> /// <param name="String">name of method /// </param> /// <param name="Object[]">params /// </param> /// <returns>Method /// /// </returns> public virtual System.Reflection.MethodInfo find(System.String methodName, System.Object[] params_Renamed) { IList methodList = (IList)methodByNameMap[methodName]; if (methodList == null) { return(null); } System.Type[] parameterTypes = null; System.Reflection.MethodInfo method = null; int numMethods = methodList.Count; int bestDistance = -2; System.Reflection.MethodInfo bestMethod = null; Twonk bestTwonk = null; bool ambiguous = false; for (int i = 0; i < numMethods; i++) { method = (System.Reflection.MethodInfo)methodList[i]; parameterTypes = GetMethodParameterTypes(method); /* * The methods we are trying to compare must * the same number of arguments. */ if (parameterTypes.Length == params_Renamed.Length) { /* * use the calling parameters as the baseline * and calculate the 'distance' from the parameters * to the method args. This will be useful when * determining specificity */ Twonk twonk = calcDistance(params_Renamed, parameterTypes); if (twonk != null) { /* * if we don't have anything yet, take it */ if (bestTwonk == null) { bestTwonk = twonk; bestMethod = method; } else { /* * now see which is more specific, this current * versus what we think of as the best candidate */ int val = twonk.moreSpecific(bestTwonk); //System.out.println("Val = " + val + " for " + method + " vs " + bestMethod ); if (val == 0) { /* * this means that the parameters 'crossed' * therefore, it's ambiguous because one is as * good as the other */ ambiguous = true; } else if (val == 1) { /* * the current method is clearly more * specific than the current best, so * we take the current we are testing * and clear the ambiguity flag */ ambiguous = false; bestTwonk = twonk; bestMethod = method; } } } } } /* * if ambiguous is true, it means we couldn't decide * so inform the caller... */ if (ambiguous) { throw new AmbiguousException(); } return(bestMethod); }
/// <summary> Calculates the distance, expressed as a vector of inheritance /// steps, between the calling args and the method args. /// There still is an issue re interfaces... /// </summary> private Twonk calcDistance(System.Object[] set , System.Type[] base_Renamed) { if (set.Length != base_Renamed.Length) { return(null); } Twonk twonk = new Twonk(set.Length); int distance = 0; for (int i = 0; i < set.Length; i++) { /* * can I get from here to there? */ System.Type setclass = set [i].GetType(); if (!base_Renamed[i].IsAssignableFrom(set [i].GetType())) { return(null); } /* * ok, I can. How many steps? */ System.Type c = setclass; while (c != null) { /* * is this a valid step? */ if (!base_Renamed[i].IsAssignableFrom(c)) { /* * it stopped being assignable - therefore we are looking at * an interface as our target, so move back one step * from the distance as the stop wasn't valid */ break; } if (base_Renamed[i].Equals(c)) { /* * we are equal, so no need to move forward */ break; } c = c.BaseType; twonk.distance++; twonk.vec[i]++; } } return(twonk); }