/// <summary> /// Builds a parameter list given a list of arguments and a list of parameter info /// </summary> /// <param name="args">A list of Values which will be distributed to the output lists</param> /// <param name="pi">An array of parameter info for the method</param> /// <param name="end">The end count</param> /// <param name="parameters">A parameters List to add to.</param> private static void BuildParameterList(FSharpList <Value> args, ParameterInfo[] pi, int end, List <List <object> > parameters) { //for a static method, the number of parameters //will equal the number of arguments on the node if (args.Count() == pi.Count()) { //ARGUMENT LOOP for (int j = 0; j < end; j++) { //create a list to hold each set of arguments var currParams = new List <object>(); //PARAMETER LOOP for (int i = 0; i < pi.Count(); i++) { var arg = args[i]; //if the value is a list, add the jth item converted //or the last item if i exceeds the count of the list if (arg.IsList) { var lst = (Value.List)arg; var argItem = (j < lst.Item.Count() ? lst.Item[j] : lst.Item.Last()); currParams.Add(DynamoTypeConverter.ConvertInput(argItem, pi[i].ParameterType)); } else { //if the value is not a list, //just add the value currParams.Add(DynamoTypeConverter.ConvertInput(arg, pi[i].ParameterType)); } } parameters.Add(currParams); } } //for instance methods, the first argument will be the //item or list of items which will be the target of invocation //in this case, skip parsing the first argument else { //ARGUMENT LOOP for (int j = 0; j < end; j++) { //create a list to hold each set of arguments var currParams = new List <object>(); //PARAMETER LOOP for (int i = 0; i < pi.Count(); i++) { var arg = args[i + 1]; //if the value is a list, add the jth item converted //or the last item if i exceeds the count of the list if (arg.IsList) { //var argItem = ((Value.List)arg).Item.Count() < end ? args.Last() : args[j]; var lst = (Value.List)arg; var argItem = (j < lst.Item.Count() ? lst.Item[j] : lst.Item.Last()); currParams.Add(DynamoTypeConverter.ConvertInput(argItem, pi[i].ParameterType)); } else { //if the value is not a list, //just add the value currParams.Add(DynamoTypeConverter.ConvertInput(arg, pi[i].ParameterType)); } } parameters.Add(currParams); } } }
/// <summary> /// Convert an input Value into and expected type if possible. /// Ex. If a node expects an XYZ, a user can pass in a ReferencePoint object /// and the position (XYZ) of that object will be returned. /// </summary> /// <param name="input">The value of the input.</param> /// <param name="output">The desired output type.</param> /// <returns></returns> public static object ConvertInput(Value input, Type output) { if (input.IsContainer) { object item = ((Value.Container)input).Item; #region ModelCurve if (item.GetType() == typeof(ModelCurve)) { ModelCurve a = (ModelCurve)item; if (output == typeof(Curve)) { return(((ModelCurve)item).GeometryCurve); } } #endregion #region SketchPlane else if (item.GetType() == typeof(SketchPlane)) { SketchPlane a = (SketchPlane)item; if (output == typeof(Plane)) { return(a.Plane); } else if (output == typeof(ReferencePlane)) { return(a.Plane); } else if (output == typeof(string)) { return(string.Format("{0},{1},{2},{3},{4},{5}", a.Plane.Origin.X, a.Plane.Origin.Y, a.Plane.Origin.Z, a.Plane.Normal.X, a.Plane.Normal.Y, a.Plane.Normal.Z)); } } #endregion #region Point else if (item.GetType() == typeof(Point)) { Point a = (Point)item; if (output == typeof(XYZ)) { return(a.Coord); } else if (output == typeof(string)) { return(string.Format("{0},{1},{2}", a.Coord.X, a.Coord.Y, a.Coord.Z)); } } #endregion #region ReferencePoint else if (item.GetType() == typeof(ReferencePoint)) { ReferencePoint a = (ReferencePoint)item; if (output == typeof(XYZ)) { return(a.Position); } else if (output == typeof(Reference)) { return(a.GetCoordinatePlaneReferenceXY()); } else if (output == typeof(Transform)) { return(a.GetCoordinateSystem()); } else if (output == typeof(string)) { return(string.Format("{0},{1},{2}", a.Position.X, a.Position.Y, a.Position.Z)); } else if (output == typeof(ElementId)) { return(a.Id); } } #endregion #region ElementId else if (item.GetType() == typeof(ElementId)) { if (output == typeof(ReferencePoint)) { ElementId a = (ElementId)item; Element el = dynRevitSettings.Doc.Document.GetElement(a); ReferencePoint rp = (ReferencePoint)el; return(rp); } } #endregion #region Reference else if (item.GetType() == typeof(Reference)) { Reference a = (Reference)item; if (output.IsAssignableFrom(typeof(Element))) { Element e = dynRevitSettings.Doc.Document.GetElement(a); } else if (output == typeof(Face)) { Face f = (Face)dynRevitSettings.Doc.Document.GetElement(a.ElementId).GetGeometryObjectFromReference(a); return(f); } } #endregion #region XYZ if (item.GetType() == typeof(XYZ)) { XYZ a = (XYZ)item; if (output == typeof(Transform)) { Transform t = Transform.get_Translation(a); return(t); } } #endregion return(item); } else if (input.IsNumber) { double a = (double)((Value.Number)input).Item; if (output == typeof(bool)) { return(Convert.ToBoolean(a)); } else if (output == typeof(Int32)) { return(Convert.ToInt32(a)); } return(a); } else if (input.IsString) { string a = ((Value.String)input).Item.ToString(); return(a); } else if (input.IsList) { FSharpList <Value> a = ((Value.List)input).Item; if (output == typeof(ReferenceArrayArray)) { return(DynamoTypeConverter.ConvertFSharpListListToReferenceArrayArray(a)); } else if (output == typeof(ReferenceArray)) { return(DynamoTypeConverter.ConvertFSharpListListToReferenceArray(a)); } else if (output == typeof(CurveArrArray)) { return(DynamoTypeConverter.ConvertFSharpListListToCurveArray(a)); } else if (output == typeof(CurveArray)) { return(DynamoTypeConverter.ConvertFSharpListListToCurveArray(a)); } return(a); } //return the input by default return(input); }
/// <summary> /// Invoke an API method, using the node's lacing strategy to build lists of arguments /// </summary> /// <param name="node">The node.</param> /// <param name="args">The incoming Values on the node.</param> /// <param name="api_base_type">The API's base type whose method we will invoke.</param> /// <param name="pi">An array of parameter info for the method.</param> /// <param name="mi">The method info for the method.</param> /// <param name="return_type">The expected return type from the method.</param> /// <returns></returns> public static Value InvokeAPIMethod(RevitTransactionNode node, FSharpList <Value> args, Type api_base_type, ParameterInfo[] pi, MethodBase mi, Type return_type) { //if any argument are a list, honor the lacing strategy //compile a list of parameter lists to be used in our method invocation List <List <object> > parameters = null; switch (node.ArgumentLacing) { case LacingStrategy.First: parameters = GetSingleArguments(args, pi); break; case LacingStrategy.Shortest: parameters = GetShortestArguments(args, pi); break; case LacingStrategy.Longest: parameters = GetLongestArguments(args, pi); break; default: parameters = GetSingleArguments(args, pi); break; } var invocationTargetList = new List <object>(); if (api_base_type == typeof(Document) || api_base_type == typeof(FamilyItemFactory) || api_base_type == typeof(ItemFactoryBase)) { if (dynRevitSettings.Doc.Document.IsFamilyDocument) { invocationTargetList.Add(dynRevitSettings.Doc.Document.FamilyCreate); } else { invocationTargetList.Add(dynRevitSettings.Doc.Document.Create); } } else if (api_base_type == typeof(Application)) { invocationTargetList.Add(dynRevitSettings.Revit.Application.Create); } else { if (!mi.IsStatic && !mi.IsConstructor) { if (args[0].IsList) { invocationTargetList.AddRange(((Value.List)args[0]).Item.Select(x => DynamoTypeConverter.ConvertInput(x, api_base_type))); } else { //the first input will always hold the instance //whose methods you want to invoke invocationTargetList.Add(DynamoTypeConverter.ConvertInput(args[0], api_base_type)); } } } //object result = null; List <object> results = null; //if the method info is for a constructor, then //call the constructor for each set of parameters //if it's an instance method, then invoke the method for //each instance passed in. results = mi.IsConstructor ? parameters.Select(x => ((ConstructorInfo)mi).Invoke(x.ToArray())).ToList() : invocationTargetList.SelectMany(x => parameters.Select(y => mi.Invoke(x, y.ToArray())).ToList()).ToList(); StoreElements(node, results); return(ConvertAllResults(results)); }