Skip to content
This repository was archived by the owner on Jan 3, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/Pather.CSharp/IResolver.cs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -41,5 +43,14 @@ public interface IResolver
/// <param name="path"></param>
/// <returns></returns>
object ResolveSafe(object target, string path);

/// <summary>
/// extract field path by a lambda expression<br/>
/// usage example: ExtractPath(()=>student.subjects[0].score) returns "student.subjects[0].score"
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lambdaExpression"></param>
/// <returns></returns>
string ExtractPath<T>(Expression<Func<T>> lambdaExpression);
}
}
1 change: 1 addition & 0 deletions src/Pather.CSharp/Pather.CSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

<ItemGroup>
<PackageReference Include="System.Linq" Version="4.3.0" />
<PackageReference Include="System.Linq.Expressions" Version="4.3.0" />
<PackageReference Include="System.Reflection" Version="4.3.0" />
<PackageReference Include="System.Reflection.Extensions" Version="4.3.0" />
<PackageReference Include="System.Runtime" Version="4.3.0" />
Expand Down
23 changes: 20 additions & 3 deletions src/Pather.CSharp/Resolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -40,7 +42,7 @@ public IList<IPathElement> 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
Expand Down Expand Up @@ -76,7 +78,7 @@ public object Resolve(object target, IList<IPathElement> 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();
Expand Down Expand Up @@ -111,5 +113,20 @@ public object ResolveSafe(object target, string path)
return null;
}
}

public string ExtractPath<T>(Expression<Func<T>> 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}");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
Expand Down
69 changes: 69 additions & 0 deletions test/Pather.CSharp.UnitTests/ResolveTests.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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 = "[email protected]"
},
Students = new List<Student>()
{
new Student(){ Name = "Jack",
Subjects = new Subject[] {
new Subject(){Name = "English",Score = 80},
new Subject(){Name = "Math",Score=90}
},
Skills = new Dictionary<string, double>()
{
{ "cook",80 },
{ "football",60}
},
Scores = new Dictionary<string, Subject>()
{
{"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<string, double>()
{
{ "cook",80 },
{ "football",60}
},
Scores = new Dictionary<string, Subject>()
{
{"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");
}
}
}
13 changes: 13 additions & 0 deletions test/Pather.CSharp.UnitTests/TestModels/Address.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
17 changes: 17 additions & 0 deletions test/Pather.CSharp.UnitTests/TestModels/Class.cs
Original file line number Diff line number Diff line change
@@ -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<Student> Students { get; set; }

public Address Address { get; set; }
}
}
20 changes: 20 additions & 0 deletions test/Pather.CSharp.UnitTests/TestModels/Student.cs
Original file line number Diff line number Diff line change
@@ -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<string,double> Skills { get; set; }

public Dictionary<string,Subject> Scores { get; set; }
}
}
14 changes: 14 additions & 0 deletions test/Pather.CSharp.UnitTests/TestModels/Subject.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}