public ParamTreeNode(Type t, ParamTree.NodeFlags flags) { ParamType = t; Flags = flags; Methods = new List <MethodTracker>(); Children = new List <ParamTreeNode>(); }
public ParamTreeNode AppendChild(MethodTracker method, Type curType, ParamTree.NodeFlags flags, bool fLastArg) { bool fFound = false; ParamTreeNode res = this; for (int i = 0; i < Children.Count; i++) { if (Children[i].ParamType == curType && Children[i].Flags == flags) { res = Children[i]; res.Methods.Add(method); fFound = true; break; } } if (!fFound) { res = InsertNewNode(curType, flags); res.Methods.Add(method); } else if (fLastArg) { // last node, we shouldn't be adding // extra methods here. We have two ways // we get here: // 1. We have a static and non-static overload, prefer the instance method // 2. We have default values for one of the methods, prefer the one w/o defaults. // // Both of these are identical checks: We prefer the method w/ less parameters. Debug.Assert(res.Methods.Count == 2); if (method.GetParameters().Length < res.Methods[0].GetParameters().Length) { // remove the old one. res.Methods.RemoveAt(0); } else { // remove the new one. res.Methods.RemoveAt(1); } } return(res); }
private ParamTreeNode InsertNewNode(Type newNodeType, ParamTree.NodeFlags flags) { ParamTreeNode newNode = new ParamTreeNode(newNodeType, flags); if (newNodeType != null) { // we've made the node, use the element type for the checks below... if (newNodeType.IsByRef) { newNodeType = newNodeType.GetElementType(); } // insert based upon subclassing order (if we're a subclass // of someone we need to come first). When we walk the tree we'll // then emit checks for more specific types before less specific types. OpsReflectedType newDt = Ops.GetDynamicTypeFromType(newNodeType) as OpsReflectedType; Type extensibleType = null; if (newDt != null) { extensibleType = newDt.GetTypeToExtend(); } if (newNodeType != typeof(object)) { for (int i = 0; i < Children.Count; i++) { Type childParamType = Children[i].ParamType; if (childParamType == null) { // params method w/ mixed levels, no subclasses checks to be done. continue; } if (childParamType.IsByRef) { childParamType = childParamType.GetElementType(); } // extensible types are logically subclasses of their "parent" type, and // therefore their check needs to go first. If extensible is added first // then the real type will come next automatically, otherwise we'll // check for the type here & early out if we're adding the extensible type. if (newNodeType == extensibleType && childParamType == newDt.type) { Children.Insert(i, newNode); return(newNode); } if (newNodeType.IsSubclassOf(childParamType) || (newNodeType.IsClass && childParamType.IsInterface)) // classes before interfaces { Children.Insert(i, newNode); return(newNode); } } } } Children.Add(newNode); return(newNode); }