Skip to content

Commit 19ce94d

Browse files
author
Sébastien Geiser
committed
Nested struct assignation OK
1 parent d3ac37e commit 19ce94d

File tree

1 file changed

+58
-13
lines changed

1 file changed

+58
-13
lines changed

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,7 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
17191719
{
17201720
object obj = stack.Pop();
17211721
Type objType = null;
1722+
ValueTypeNestingTrace valueTypeNestingTrace = null;
17221723

17231724
if (obj != null && TypesToBlock.Contains(obj.GetType()))
17241725
throw new ExpressionEvaluatorSecurityException($"{obj.GetType().FullName} type is blocked");
@@ -1746,7 +1747,7 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
17461747
else
17471748
{
17481749
List<object> oArgs = funcArgs.ConvertAll(arg => Evaluate(arg));
1749-
BindingFlags flag = DetermineInstanceOrStatic(ref objType, ref obj);
1750+
BindingFlags flag = DetermineInstanceOrStatic(ref objType, ref obj, ref valueTypeNestingTrace);
17501751

17511752
if (!OptionStaticMethodsCallActive && (flag & BindingFlags.Static) != 0)
17521753
throw new ExpressionEvaluatorSyntaxErrorException($"[{objType}] object has no Method named \"{varFuncName}\".");
@@ -1923,6 +1924,7 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
19231924

19241925
object obj = stack.Pop();
19251926
Type objType = null;
1927+
ValueTypeNestingTrace valueTypeNestingTrace = null;
19261928

19271929
if (obj != null && TypesToBlock.Contains(obj.GetType()))
19281930
throw new ExpressionEvaluatorSecurityException($"{obj.GetType().FullName} type is blocked");
@@ -1949,7 +1951,7 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
19491951
}
19501952
else
19511953
{
1952-
BindingFlags flag = DetermineInstanceOrStatic(ref objType, ref obj);
1954+
BindingFlags flag = DetermineInstanceOrStatic(ref objType, ref obj, ref valueTypeNestingTrace);
19531955

19541956
if (!OptionStaticProperiesGetActive && (flag & BindingFlags.Static) != 0)
19551957
throw new ExpressionEvaluatorSyntaxErrorException($"[{objType}] object has no public Property or Field named \"{varFuncName}\".");
@@ -1978,10 +1980,22 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
19781980
else
19791981
{
19801982
varValue = ((dynamic)member).GetValue(obj);
1983+
1984+
if (varValue is ValueType valueType && member is FieldInfo fieldInfo)
1985+
{
1986+
varValue = valueTypeNestingTrace = new ValueTypeNestingTrace
1987+
{
1988+
Container = valueTypeNestingTrace ?? obj,
1989+
Field = fieldInfo,
1990+
Value = valueType
1991+
};
1992+
}
19811993
}
19821994

19831995
if (pushVarValue)
1996+
{
19841997
stack.Push(varValue);
1998+
}
19851999

19862000
if (OptionPropertyOrFieldSetActive)
19872001
{
@@ -2027,16 +2041,15 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
20272041
}
20282042
else
20292043
{
2030-
//if (objType.IsValueType && member is FieldInfo fieldInfo)
2031-
//{
2032-
// Action<object, object> setter = GetDelegateForStruct(objType, fieldInfo);
2033-
// ValueType valueType = obj as ValueType;
2034-
// setter(valueType, varValue);
2035-
//}
2036-
//else
2037-
//{
2044+
if (valueTypeNestingTrace != null)
2045+
{
2046+
valueTypeNestingTrace.Value = varValue;
2047+
valueTypeNestingTrace.AssignValue();
2048+
}
2049+
else
2050+
{
20382051
((dynamic)member).SetValue(obj, varValue);
2039-
//}
2052+
}
20402053
}
20412054
}
20422055
}
@@ -2500,7 +2513,9 @@ private bool EvaluateString(string expr, string s, string restOfExpression, Stac
25002513

25012514
private object ProcessStack(Stack<object> stack)
25022515
{
2503-
List<object> list = stack.ToList();
2516+
List<object> list = stack
2517+
.Select(e => e is ValueTypeNestingTrace valueTypeNestingTrace ? valueTypeNestingTrace.Value : e)
2518+
.ToList();
25042519

25052520
operatorsEvaluations.ForEach((Dictionary<ExpressionOperator, Func<dynamic, dynamic, object>> operatorEvalutationsDict) =>
25062521
{
@@ -2759,8 +2774,15 @@ private Type[] GetConcreteTypes(string genericsTypes)
27592774
.ToArray();
27602775
}
27612776

2762-
private BindingFlags DetermineInstanceOrStatic(ref Type objType, ref object obj)
2777+
private BindingFlags DetermineInstanceOrStatic(ref Type objType, ref object obj, ref ValueTypeNestingTrace valueTypeNestingTrace)
27632778
{
2779+
valueTypeNestingTrace = obj as ValueTypeNestingTrace;
2780+
2781+
if(valueTypeNestingTrace != null)
2782+
{
2783+
obj = valueTypeNestingTrace.Value;
2784+
}
2785+
27642786
if (obj is ClassOrTypeName classOrTypeName)
27652787
{
27662788
objType = classOrTypeName.Type;
@@ -3095,6 +3117,29 @@ private class ClassOrTypeName
30953117
public Type Type { get; set; }
30963118
}
30973119

3120+
private class ValueTypeNestingTrace
3121+
{
3122+
public object Container { get; set; }
3123+
3124+
public FieldInfo Field { get; set; }
3125+
3126+
public object Value { get; set; }
3127+
3128+
public void AssignValue()
3129+
{
3130+
if(Container is ValueTypeNestingTrace valueTypeNestingTrace)
3131+
{
3132+
Field.SetValue(valueTypeNestingTrace.Value, Value);
3133+
valueTypeNestingTrace.AssignValue();
3134+
}
3135+
else
3136+
{
3137+
Field.SetValue(Container, Value);
3138+
}
3139+
3140+
}
3141+
}
3142+
30983143
private class DelegateEncaps
30993144
{
31003145
private readonly InternalDelegate lambda;

0 commit comments

Comments
 (0)