Skip to content

Commit b502ef3

Browse files
authored
feat: allow default values for generic parameters (#239)
generalize default expressions for generic methods
1 parent 178569e commit b502ef3

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

src/DynamicExpresso.Core/Parsing/Parser.cs

+37-1
Original file line numberDiff line numberDiff line change
@@ -2004,6 +2004,37 @@ private static MethodData[] FindBestMethod(IEnumerable<MethodData> methods, Expr
20042004
return applicable;
20052005
}
20062006

2007+
private static Type GetConcreteTypeForGenericMethod(Type type, List<Expression> promotedArgs, MethodData method)
2008+
{
2009+
if (type.IsGenericType)
2010+
{
2011+
//Generic<T> type
2012+
var genericArguments = type.GetGenericArguments();
2013+
var concreteTypeParameters = new Type[genericArguments.Length];
2014+
2015+
for (var i = 0; i < genericArguments.Length; i++)
2016+
{
2017+
concreteTypeParameters[i] = GetConcreteTypeForGenericMethod(genericArguments[i], promotedArgs,method);
2018+
}
2019+
2020+
return type.GetGenericTypeDefinition().MakeGenericType(concreteTypeParameters);
2021+
}
2022+
else if (type.ContainsGenericParameters)
2023+
{
2024+
//T case
2025+
//try finding an actual parameter for the generic
2026+
for (var i = 0; i < promotedArgs.Count; i++)
2027+
{
2028+
if (method.Parameters[i].ParameterType == type)
2029+
{
2030+
return promotedArgs[i].Type;
2031+
}
2032+
}
2033+
}
2034+
2035+
return type;//already a concrete type
2036+
}
2037+
20072038
private static bool CheckIfMethodIsApplicableAndPrepareIt(MethodData method, Expression[] args)
20082039
{
20092040
if (method.Parameters.Count(y => !y.HasDefaultValue && !HasParamsArrayType(y)) > args.Length)
@@ -2111,7 +2142,12 @@ private static bool CheckIfMethodIsApplicableAndPrepareIt(MethodData method, Exp
21112142
promotedArgs.AddRange(method.Parameters.Skip(promotedArgs.Count).Select<ParameterInfo, Expression>(x =>
21122143
{
21132144
if (x.HasDefaultValue)
2114-
return Expression.Constant(x.DefaultValue, x.ParameterType);
2145+
{
2146+
var parameterType = GetConcreteTypeForGenericMethod(x.ParameterType, promotedArgs, method);
2147+
2148+
return Expression.Constant(x.DefaultValue, parameterType);
2149+
}
2150+
21152151

21162152
if (HasParamsArrayType(x))
21172153
{

test/DynamicExpresso.UnitTest/MemberInvocationTest.cs

+28
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,14 @@ public void Method_with_generic_param()
322322
Assert.AreEqual(x.MethodWithGenericParam(y, y), target.Eval("x.MethodWithGenericParam(y, y)", parameters));
323323
Assert.AreEqual(x.MethodWithGenericParam(y, z), target.Eval("x.MethodWithGenericParam(y, z)", parameters));
324324
Assert.AreEqual(x.MethodWithGenericParam(y, w), target.Eval("x.MethodWithGenericParam(y, w)", parameters));
325+
326+
Assert.AreEqual(x.MethodWithGenericParamAndDefault(y,y), target.Eval("x.MethodWithGenericParamAndDefault(y,y)", parameters));
327+
Assert.AreEqual(x.MethodWithGenericParamAndDefault(y), target.Eval("x.MethodWithGenericParamAndDefault(y)", parameters));
328+
Assert.AreEqual(x.MethodWithGenericParamAndDefault1Levels(y), target.Eval("x.MethodWithGenericParamAndDefault1Levels(y)", parameters));
329+
Assert.AreEqual(x.MethodWithGenericParamAndDefault2Levels(y), target.Eval("x.MethodWithGenericParamAndDefault2Levels(y)", parameters));
330+
Assert.AreEqual(x.MethodWithGenericParamAndDefault2Levels(y, w), target.Eval("x.MethodWithGenericParamAndDefault2Levels(y, w)", parameters));
331+
332+
325333
}
326334

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

570+
public T MethodWithGenericParamAndDefault<T>(T a, T b = default)
571+
{
572+
return a;
573+
}
574+
575+
public T MethodWithGenericParamAndDefault1Levels<T>(T a, List<T> b = default)
576+
{
577+
return a;
578+
}
579+
580+
public T MethodWithGenericParamAndDefault2Levels<T>(T a, List<List<T>> b = default)
581+
{
582+
return a;
583+
}
584+
585+
public T MethodWithGenericParamAndDefault2Levels<T, T2>(T a, T2 b, List<T> c = default, List<List<T2>> d = default)
586+
{
587+
return a;
588+
}
589+
562590
public string MethodWithOptionalParam(string param1, string param2 = "2", string param3 = "3")
563591
{
564592
return string.Format("{0} {1} {2}", param1, param2, param3);

0 commit comments

Comments
 (0)