Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle HashSet, FragmentSet,... as input list #253

Merged
merged 3 commits into from
May 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions BHoM_UI/Components/oM/CreateObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
using BH.Engine.UI;
using System.Windows.Forms;
using BH.oM.Base;
using System.Collections;

namespace BH.UI.Components
{
Expand Down Expand Up @@ -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<ParamInfo> inputParams = new List<ParamInfo>();
if (component.CustomData.TryGetValue("InputParams", out inputParamsRecord))
InputParams = (inputParamsRecord as IEnumerable).OfType<ParamInfo>().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)
{
Expand Down
47 changes: 36 additions & 11 deletions BHoM_UI/Templates/Caller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -469,17 +470,41 @@ protected virtual Func<DataAccessor, object> CreateInputAccessor(Type dataType,
MethodCallExpression methodExpression = Expression.Call(Expression.Convert(lambdaInput1, DataAccessor.GetType()), method, methodInputs);
Func<DataAccessor, object> lambda = Expression.Lambda<Func<DataAccessor, object>>(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<object, object> castDelegate = Expression.Lambda<Func<object, object>>(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<object, object> castDelegate = Expression.Lambda<Func<object, object>>(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<object, object> castDelegate = Expression.Lambda<Func<object, object>>(castExpression, lambdaResult).Compile();

return (accessor) => { return castDelegate(lambda(accessor)); };
}

/*******************************************/
Expand Down