diff --git a/BHoM_UI/Components/oM/CreateObject.cs b/BHoM_UI/Components/oM/CreateObject.cs index 1a454126..25ba9531 100644 --- a/BHoM_UI/Components/oM/CreateObject.cs +++ b/BHoM_UI/Components/oM/CreateObject.cs @@ -33,6 +33,7 @@ using BH.Engine.UI; using System.Windows.Forms; using BH.oM.Base; +using System.Collections; namespace BH.UI.Components { @@ -241,13 +242,31 @@ public override bool Read(string json) SelectedItem = type; SetInputSelectionMenu(type, InputParams.Select(x => x.Name)); } - } } + + if (SelectedItem is Type) + m_CompiledFunc = Engine.UI.Compute.Constructor((Type)SelectedItem, InputParams); } - if (SelectedItem is Type) - m_CompiledFunc = Engine.UI.Compute.Constructor((Type)SelectedItem, InputParams); + else if (SelectedItem is Type) + { + CustomObject component = Engine.Serialiser.Convert.FromJson(json) as CustomObject; + if (component != null && component.CustomData.ContainsKey("InputParams")) + { + object inputParamsRecord; + List inputParams = new List(); + if (component.CustomData.TryGetValue("InputParams", out inputParamsRecord)) + InputParams = (inputParamsRecord as IEnumerable).OfType().ToList(); + + Type type = SelectedItem as Type; + SetInputSelectionMenu(type, InputParams.Select(x => x.Name)); + + m_CompiledFunc = Engine.UI.Compute.Constructor(type, InputParams); + CompileInputGetters(); + } + } + } catch (Exception e) { diff --git a/BHoM_UI/Templates/Caller.cs b/BHoM_UI/Templates/Caller.cs index f4901cf8..481e5b4d 100644 --- a/BHoM_UI/Templates/Caller.cs +++ b/BHoM_UI/Templates/Caller.cs @@ -299,7 +299,8 @@ public virtual bool Read(string json) SetItem(backendElement); WasUpgraded = backendElement != null; } - SetItem(backendElement); + else + SetItem(backendElement); } // We also overwrite the InputParams and OutputParams, since we could have made some changes to them - e.g. ListInput @@ -375,7 +376,7 @@ protected virtual object[] CollectInputs() catch (Exception e) { RecordError(e, "This component failed to run properly. Inputs cannot be collected properly.\n"); - inputs = null; + return null; } return inputs.ToArray(); @@ -469,17 +470,41 @@ protected virtual Func CreateInputAccessor(Type dataType, MethodCallExpression methodExpression = Expression.Call(Expression.Convert(lambdaInput1, DataAccessor.GetType()), method, methodInputs); Func lambda = Expression.Lambda>(Expression.Convert(methodExpression, typeof(object)), lambdaInputs).Compile(); - if (!dataType.IsArray) + if (dataType.IsArray) + { + // If dataType is an array type, the underlying method asks for an array type + // Thus, we add a new node to the syntax tree that casts the List to an Array + MethodInfo castMethod = typeof(Enumerable).GetMethod("ToArray").MakeGenericMethod(subType.Type); + ParameterExpression lambdaResult = Expression.Parameter(typeof(object), "lambdaResult"); + MethodCallExpression castExpression = Expression.Call(null, castMethod, Expression.Convert(lambdaResult, typeof(IEnumerable<>).MakeGenericType(subType.Type))); + Func castDelegate = Expression.Lambda>(castExpression, lambdaResult).Compile(); + + return (accessor) => { return castDelegate(lambda(accessor)); }; + } + else if (subType.Depth == 1 && dataType.Name != "List`1" && dataType.Name != "IEnumerable`1") + { + // If we have a `DataList` that isn't actually a list, lets try to create it from teh list through the appropriate constructor + foreach (ConstructorInfo constructor in dataType.GetConstructors()) + { + ParameterInfo[] parameters = constructor.GetParameters(); + if (parameters.Count() == 1) + { + string paramType = parameters[0].ParameterType.Name; + if (paramType == "List`1" || paramType == "IEnumerable`1") + { + ParameterExpression lambdaResult = Expression.Parameter(typeof(object), "lambdaResult"); + NewExpression castExpression = Expression.New(constructor, Expression.Convert(lambdaResult, parameters[0].ParameterType)); + Func castDelegate = Expression.Lambda>(castExpression, lambdaResult).Compile(); + return (accessor) => { return castDelegate(lambda(accessor)); }; + } + } + } return lambda; + } + else + return lambda; + - // If dataType is an array type, the underlying method asks for an array type - // Thus, we add a new node to the syntax tree that casts the List to an Array - MethodInfo castMethod = typeof(Enumerable).GetMethod("ToArray").MakeGenericMethod(subType.Type); - ParameterExpression lambdaResult = Expression.Parameter(typeof(object), "lambdaResult"); - MethodCallExpression castExpression = Expression.Call(null, castMethod, Expression.Convert(lambdaResult, typeof(IEnumerable<>).MakeGenericType(subType.Type))); - Func castDelegate = Expression.Lambda>(castExpression, lambdaResult).Compile(); - - return (accessor) => { return castDelegate(lambda(accessor)); }; } /*******************************************/