Skip to content

Commit

Permalink
feat: allow default values for generic parameters (#239)
Browse files Browse the repository at this point in the history
generalize default expressions for generic methods
  • Loading branch information
israellot authored Jun 14, 2022
1 parent 178569e commit b502ef3
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
38 changes: 37 additions & 1 deletion src/DynamicExpresso.Core/Parsing/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2004,6 +2004,37 @@ private static MethodData[] FindBestMethod(IEnumerable<MethodData> methods, Expr
return applicable;
}

private static Type GetConcreteTypeForGenericMethod(Type type, List<Expression> promotedArgs, MethodData method)
{
if (type.IsGenericType)
{
//Generic<T> type
var genericArguments = type.GetGenericArguments();
var concreteTypeParameters = new Type[genericArguments.Length];

for (var i = 0; i < genericArguments.Length; i++)
{
concreteTypeParameters[i] = GetConcreteTypeForGenericMethod(genericArguments[i], promotedArgs,method);
}

return type.GetGenericTypeDefinition().MakeGenericType(concreteTypeParameters);
}
else if (type.ContainsGenericParameters)
{
//T case
//try finding an actual parameter for the generic
for (var i = 0; i < promotedArgs.Count; i++)
{
if (method.Parameters[i].ParameterType == type)
{
return promotedArgs[i].Type;
}
}
}

return type;//already a concrete type
}

private static bool CheckIfMethodIsApplicableAndPrepareIt(MethodData method, Expression[] args)
{
if (method.Parameters.Count(y => !y.HasDefaultValue && !HasParamsArrayType(y)) > args.Length)
Expand Down Expand Up @@ -2111,7 +2142,12 @@ private static bool CheckIfMethodIsApplicableAndPrepareIt(MethodData method, Exp
promotedArgs.AddRange(method.Parameters.Skip(promotedArgs.Count).Select<ParameterInfo, Expression>(x =>
{
if (x.HasDefaultValue)
return Expression.Constant(x.DefaultValue, x.ParameterType);
{
var parameterType = GetConcreteTypeForGenericMethod(x.ParameterType, promotedArgs, method);

return Expression.Constant(x.DefaultValue, parameterType);
}


if (HasParamsArrayType(x))
{
Expand Down
28 changes: 28 additions & 0 deletions test/DynamicExpresso.UnitTest/MemberInvocationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,14 @@ public void Method_with_generic_param()
Assert.AreEqual(x.MethodWithGenericParam(y, y), target.Eval("x.MethodWithGenericParam(y, y)", parameters));
Assert.AreEqual(x.MethodWithGenericParam(y, z), target.Eval("x.MethodWithGenericParam(y, z)", parameters));
Assert.AreEqual(x.MethodWithGenericParam(y, w), target.Eval("x.MethodWithGenericParam(y, w)", parameters));

Assert.AreEqual(x.MethodWithGenericParamAndDefault(y,y), target.Eval("x.MethodWithGenericParamAndDefault(y,y)", parameters));
Assert.AreEqual(x.MethodWithGenericParamAndDefault(y), target.Eval("x.MethodWithGenericParamAndDefault(y)", parameters));
Assert.AreEqual(x.MethodWithGenericParamAndDefault1Levels(y), target.Eval("x.MethodWithGenericParamAndDefault1Levels(y)", parameters));
Assert.AreEqual(x.MethodWithGenericParamAndDefault2Levels(y), target.Eval("x.MethodWithGenericParamAndDefault2Levels(y)", parameters));
Assert.AreEqual(x.MethodWithGenericParamAndDefault2Levels(y, w), target.Eval("x.MethodWithGenericParamAndDefault2Levels(y, w)", parameters));


}

[Test]
Expand Down Expand Up @@ -559,6 +567,26 @@ public string MethodWithGenericParam<T>(string a, T p)
return string.Format("{0} {1}", a, p);
}

public T MethodWithGenericParamAndDefault<T>(T a, T b = default)
{
return a;
}

public T MethodWithGenericParamAndDefault1Levels<T>(T a, List<T> b = default)
{
return a;
}

public T MethodWithGenericParamAndDefault2Levels<T>(T a, List<List<T>> b = default)
{
return a;
}

public T MethodWithGenericParamAndDefault2Levels<T, T2>(T a, T2 b, List<T> c = default, List<List<T2>> d = default)
{
return a;
}

public string MethodWithOptionalParam(string param1, string param2 = "2", string param3 = "3")
{
return string.Format("{0} {1} {2}", param1, param2, param3);
Expand Down

0 comments on commit b502ef3

Please sign in to comment.