Skip to content

Commit 8af487a

Browse files
committed
Allow properties or fields to contain periods
1 parent b45ef61 commit 8af487a

File tree

1 file changed

+58
-2
lines changed

1 file changed

+58
-2
lines changed

src/Mapster/Utils/ExpressionEx.cs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,64 @@ public static Expression Assign(Expression left, Expression right)
1919

2020
public static Expression PropertyOrFieldPath(Expression expr, string path)
2121
{
22-
var props = path.Split('.');
23-
return props.Aggregate(expr, PropertyOrField);
22+
Expression current = expr;
23+
string[] props = path.Split('.');
24+
25+
for (int i = 0; i < props.Length; i++)
26+
{
27+
Exception initialException;
28+
29+
try
30+
{
31+
string prop = props[i];
32+
current = PropertyOrField(current, prop);
33+
continue;
34+
}
35+
catch (Exception ex) when (props.Length - i > 1) // Only catch when parts remain
36+
{
37+
// Store the exception to rethrow in the end if the alternative approach fails
38+
initialException = ex;
39+
}
40+
41+
// For dynamically built types, it is possible to have periods in the property name.
42+
// Rejoin an incrementing number of parts with periods to try and find a property match.
43+
try
44+
{
45+
(current, int combinationLength) = PropertyOrFieldPathWithPeriods(current, props[i..]);
46+
i += combinationLength - 1;
47+
}
48+
catch
49+
{
50+
// Rethrow the original exception for the first part
51+
ExceptionDispatchInfo.Capture(initialException).Throw();
52+
}
53+
}
54+
55+
return current;
56+
}
57+
58+
private static (Expression Expression, int CombinationLength) PropertyOrFieldPathWithPeriods(Expression expr, string[] path)
59+
{
60+
if (path.Length < 2)
61+
{
62+
throw new ArgumentException($"Value should contain at least 2 elements, got {path.Length}.", nameof(path));
63+
}
64+
65+
for (int count = 2; count <= path.Length; count++)
66+
{
67+
try
68+
{
69+
string prop = string.Join('.', path[..count]);
70+
return (PropertyOrField(expr, prop), count);
71+
}
72+
catch when (count < path.Length)
73+
{
74+
// Only throw for the last element, no property or field was found
75+
}
76+
}
77+
78+
// This is not reachable, right?
79+
throw new NotSupportedException("This should not be reachable.");
2480
}
2581

2682
private static Expression PropertyOrField(Expression expr, string prop)

0 commit comments

Comments
 (0)