diff --git a/src/Pather.CSharp/IResolver.cs b/src/Pather.CSharp/IResolver.cs
index c3b2a4d..a7ca6ae 100644
--- a/src/Pather.CSharp/IResolver.cs
+++ b/src/Pather.CSharp/IResolver.cs
@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
using Pather.CSharp.PathElements;
namespace Pather.CSharp
@@ -41,5 +43,14 @@ public interface IResolver
///
///
object ResolveSafe(object target, string path);
+
+ ///
+ /// extract field path by a lambda expression
+ /// usage example: ExtractPath(()=>student.subjects[0].score) returns "student.subjects[0].score"
+ ///
+ ///
+ ///
+ ///
+ string ExtractPath(Expression> lambdaExpression);
}
}
\ No newline at end of file
diff --git a/src/Pather.CSharp/Pather.CSharp.csproj b/src/Pather.CSharp/Pather.CSharp.csproj
index e57c47c..babf220 100644
--- a/src/Pather.CSharp/Pather.CSharp.csproj
+++ b/src/Pather.CSharp/Pather.CSharp.csproj
@@ -21,6 +21,7 @@
+
diff --git a/src/Pather.CSharp/Resolver.cs b/src/Pather.CSharp/Resolver.cs
index 6251b60..cf0483d 100644
--- a/src/Pather.CSharp/Resolver.cs
+++ b/src/Pather.CSharp/Resolver.cs
@@ -4,7 +4,9 @@
using System.Threading.Tasks;
using System.Reflection;
using Pather.CSharp.PathElements;
-
+using System.Linq.Expressions;
+using System.Text.RegularExpressions;
+
namespace Pather.CSharp
{
public class Resolver : IResolver
@@ -40,7 +42,7 @@ public IList CreatePath(string path)
var tempPath = path;
while (tempPath.Length > 0)
{
- var pathElement = createPathElement(tempPath, out tempPath);
+ var pathElement = CreatePathElement(tempPath, out tempPath);
pathElements.Add(pathElement);
//remove the dots chaining properties
//no PathElement could do this reliably
@@ -76,7 +78,7 @@ public object Resolve(object target, IList pathElements)
return result;
}
- private IPathElement createPathElement(string path, out string newPath)
+ private IPathElement CreatePathElement(string path, out string newPath)
{
//get the first applicable path element type
var pathElementFactory = PathElementFactories.Where(f => f.IsApplicable(path)).FirstOrDefault();
@@ -111,5 +113,20 @@ public object ResolveSafe(object target, string path)
return null;
}
}
+
+ public string ExtractPath(Expression> lambdaExpression)
+ {
+ var expressionStr = lambdaExpression.ToString();
+
+ string pattern = @"\bvalue\([^)]*\)\.(.+)";
+ var match = Regex.Match(expressionStr, pattern);
+ if (match.Success)
+ {
+ var result = match.Groups[1].Value.Replace(".get_Item(", "[").Replace(")", "]");
+ return result;
+ }
+
+ throw new ArgumentException($"can not extract path from {expressionStr}");
+ }
}
}
diff --git a/test/Pather.CSharp.UnitTests/Pather.CSharp.UnitTests.csproj b/test/Pather.CSharp.UnitTests/Pather.CSharp.UnitTests.csproj
index 2cf17d4..b76eefe 100644
--- a/test/Pather.CSharp.UnitTests/Pather.CSharp.UnitTests.csproj
+++ b/test/Pather.CSharp.UnitTests/Pather.CSharp.UnitTests.csproj
@@ -1,4 +1,4 @@
-
+
netcoreapp2.0
diff --git a/test/Pather.CSharp.UnitTests/ResolveTests.cs b/test/Pather.CSharp.UnitTests/ResolveTests.cs
index e3d56e6..67a8c52 100644
--- a/test/Pather.CSharp.UnitTests/ResolveTests.cs
+++ b/test/Pather.CSharp.UnitTests/ResolveTests.cs
@@ -1,6 +1,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Pather.CSharp.UnitTests.TestHelper;
+using Pather.CSharp.UnitTests.TestModels;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -274,6 +275,74 @@ public void IndexerResolution_String_Success()
var res = resolver.Resolve(target, path);
res.Should().Be("Testabc");
+ }
+
+ [TestMethod]
+ public void ExtractPath_Success()
+ {
+ var myclass = new Class()
+ {
+ Name = "class 1",
+ Address = new Address()
+ {
+ Email = "abc@china.com"
+ },
+ Students = new List()
+ {
+ new Student(){ Name = "Jack",
+ Subjects = new Subject[] {
+ new Subject(){Name = "English",Score = 80},
+ new Subject(){Name = "Math",Score=90}
+ },
+ Skills = new Dictionary()
+ {
+ { "cook",80 },
+ { "football",60}
+ },
+ Scores = new Dictionary()
+ {
+ {"English", new Subject(){Score = 80} },
+ {"Math", new Subject(){Score=90} }
+ }
+ },
+ new Student(){ Name = "Timi",
+ Subjects = new Subject[] {
+ new Subject(){Name = "English",Score = 80},
+ new Subject(){Name = "Math",Score=90}
+ },
+ Skills = new Dictionary()
+ {
+ { "cook",80 },
+ { "football",60}
+ },
+ Scores = new Dictionary()
+ {
+ {"English", new Subject(){Score = 80} },
+ {"Math", new Subject(){Score=90} }
+ }
+ }
+ }
+ };
+
+ IResolver resolver = new Resolver();
+
+ var case1 = resolver.ExtractPath(() => myclass.Name);
+ case1.Should().Be("myclass.Name");
+
+ var case2 = resolver.ExtractPath(() => myclass.Address.Email);
+ case2.Should().Be("myclass.Address.Email");
+
+ var case3 = resolver.ExtractPath(() => myclass.Students);
+ case3.Should().Be("myclass.Students");
+
+ var case4 = resolver.ExtractPath(() => myclass.Students[0].Name);
+ case4.Should().Be("myclass.Students[0].Name");
+
+ var case5 = resolver.ExtractPath(() => myclass.Students[0].Subjects[0].Name);
+ case5.Should().Be("myclass.Students[0].Subjects[0].Name");
+
+ var case6 = resolver.ExtractPath(() => myclass.Students[0].Scores["Math"].Score);
+ case6.Should().Be("myclass.Students[0].Scores[\"Math\"].Score");
}
}
}
diff --git a/test/Pather.CSharp.UnitTests/TestModels/Address.cs b/test/Pather.CSharp.UnitTests/TestModels/Address.cs
new file mode 100644
index 0000000..ff214df
--- /dev/null
+++ b/test/Pather.CSharp.UnitTests/TestModels/Address.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Pather.CSharp.UnitTests.TestModels
+{
+ internal class Address
+ {
+ public string Email { get; set; }
+ }
+}
diff --git a/test/Pather.CSharp.UnitTests/TestModels/Class.cs b/test/Pather.CSharp.UnitTests/TestModels/Class.cs
new file mode 100644
index 0000000..9a1718c
--- /dev/null
+++ b/test/Pather.CSharp.UnitTests/TestModels/Class.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Pather.CSharp.UnitTests.TestModels
+{
+ internal class Class
+ {
+ public string Name { get; set; }
+
+ public List Students { get; set; }
+
+ public Address Address { get; set; }
+ }
+}
diff --git a/test/Pather.CSharp.UnitTests/TestModels/Student.cs b/test/Pather.CSharp.UnitTests/TestModels/Student.cs
new file mode 100644
index 0000000..a00c935
--- /dev/null
+++ b/test/Pather.CSharp.UnitTests/TestModels/Student.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Pather.CSharp.UnitTests.TestModels
+{
+ internal class Student
+ {
+ // 姓名
+ public string Name { get; set; }
+
+ public Subject[] Subjects { get; set; }
+
+ public Dictionary Skills { get; set; }
+
+ public Dictionary Scores { get; set; }
+ }
+}
diff --git a/test/Pather.CSharp.UnitTests/TestModels/Subject.cs b/test/Pather.CSharp.UnitTests/TestModels/Subject.cs
new file mode 100644
index 0000000..5669c5e
--- /dev/null
+++ b/test/Pather.CSharp.UnitTests/TestModels/Subject.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Pather.CSharp.UnitTests.TestModels
+{
+ internal class Subject
+ {
+ public string Name { get; set; }
+ public double Score { get; set; }
+ }
+}