瀏覽代碼

Added options to configure expression parsing; parse oderBy and filter expressions; basic filter and orderBy working; removed Id property from LuObjectsDbo; added descriptors for groups and metadata

develop
Robin Thoni 6 年之前
父節點
當前提交
316f06c4f9

+ 1
- 1
Luticate2.Auth.ConsoleSample/Commands/CreateCommand.cs 查看文件

@@ -63,7 +63,7 @@ namespace Luticate2.Auth.ConsoleSample.Commands
63 63
                 {
64 64
                     if (OutputType == "specific")
65 65
                     {
66
-                        Console.WriteLine($"{item.Id} {item.Name ?? "??"}");
66
+                        Console.WriteLine($"{item.Metadata.Id} {item.Name ?? "??"}");
67 67
                     }
68 68
                     else if (OutputType == "json-full")
69 69
                     {

+ 9
- 5
Luticate2.Auth.ConsoleSample/Commands/ListCommand.cs 查看文件

@@ -7,8 +7,10 @@ using Luticate2.Auth.Auth.Dbo;
7 7
 using Luticate2.Auth.Utils.Business.Fields;
8 8
 using Luticate2.Auth.Utils.Business.Pagination;
9 9
 using Luticate2.Auth.Utils.Business.Serializers.PartialJson;
10
+using Luticate2.Auth.Utils.Business.Utils;
10 11
 using Luticate2.Auth.Utils.Dbo.Pagination;
11 12
 using Microsoft.Extensions.DependencyInjection;
13
+using Microsoft.Extensions.Options;
12 14
 using NClap.Metadata;
13 15
 using Newtonsoft.Json;
14 16
 
@@ -25,8 +27,8 @@ namespace Luticate2.Auth.ConsoleSample.Commands
25 27
         [NamedArgument(DefaultValue = "")]
26 28
         public string Filter { get; set; }
27 29
 
28
-        [NamedArgument(DefaultValue = "id:asc")]
29
-        public string OrderBy { get; set; }
30
+        [NamedArgument(ArgumentFlags.Multiple)]
31
+        public string[] OrderBy { get; set; }
30 32
 
31 33
         [NamedArgument(DefaultValue = "0")]
32 34
         public int Page { get; set; }
@@ -45,6 +47,8 @@ namespace Luticate2.Auth.ConsoleSample.Commands
45 47
             }
46 48
             else
47 49
             {
50
+                var parserOptions = Program.ServiceProvider.GetRequiredService<IOptions<LuExpressionUtils.LuExpressionParserOptions>>();
51
+
48 52
                 var partialResponseResult = LuPartialFieldsParser.Parse(PartialResponse);
49 53
                 if (!partialResponseResult)
50 54
                 {
@@ -53,7 +57,7 @@ namespace Luticate2.Auth.ConsoleSample.Commands
53 57
                 }
54 58
                 var partialResponse = partialResponseResult.Data;
55 59
 
56
-                var filterResult = LuFilterParser.Parse<LuGroupDbo>(Filter);
60
+                var filterResult = LuFilterParser.Parse<LuGroupDbo>(Filter, parserOptions.Value);
57 61
                 if (!filterResult)
58 62
                 {
59 63
                     filterResult.WriteLineError();
@@ -61,7 +65,7 @@ namespace Luticate2.Auth.ConsoleSample.Commands
61 65
                 }
62 66
                 var filter = filterResult.Data;
63 67
 
64
-                var orderByResult = LuOrderByParser.Parse(OrderBy);
68
+                var orderByResult = LuOrderByParser.Parse<LuGroupDbo>(OrderBy, parserOptions.Value);
65 69
                 if (!orderByResult)
66 70
                 {
67 71
                     orderByResult.WriteLineError();
@@ -90,7 +94,7 @@ namespace Luticate2.Auth.ConsoleSample.Commands
90 94
                     {
91 95
                         if (OutputType == "specific")
92 96
                         {
93
-                            Console.WriteLine($"{item.Id} {item.Name ?? "??"}");
97
+                            Console.WriteLine($"{item.Metadata.Id} {item.Name ?? "??"}");
94 98
                         }
95 99
                         else if (OutputType == "json-full")
96 100
                         {

+ 30
- 3
Luticate2.Auth.ConsoleSample/Program.cs 查看文件

@@ -1,8 +1,14 @@
1 1
 using System;
2
+using System.Collections.Generic;
2 3
 using Luticate2.Auth.Auth.Business;
3 4
 using Luticate2.Auth.Auth.DataAccess;
5
+using Luticate2.Auth.Auth.DataAccess.Converters;
6
+using Luticate2.Auth.Auth.DataAccess.Models;
7
+using Luticate2.Auth.Auth.Dbo;
4 8
 using Luticate2.Auth.ConsoleSample.Commands;
5 9
 using Luticate2.Auth.Utils.Business.Converters;
10
+using Luticate2.Auth.Utils.Business.Utils;
11
+using Luticate2.Auth.Utils.Interfaces;
6 12
 using Microsoft.EntityFrameworkCore;
7 13
 using Microsoft.Extensions.DependencyInjection;
8 14
 using NClap.Metadata;
@@ -21,7 +27,7 @@ namespace Luticate2.Auth.ConsoleSample
21 27
         [Command(typeof(ExitCommand), Description = "Exits the shell")]
22 28
         Exit
23 29
     }
24
-    
30
+
25 31
     class Program
26 32
     {
27 33
         public static IServiceProvider ServiceProvider;
@@ -31,10 +37,31 @@ namespace Luticate2.Auth.ConsoleSample
31 37
             IServiceCollection services = new ServiceCollection();
32 38
 
33 39
             services.AddLuObjectConverterDescriptors();
40
+            // DB Read
41
+            services.AddSingleton<ILuObjectConverterDescriptor<LuObjectsMetadataDbo, LuObjectsMetadata>, LuObjectsMetadataDboDescriptor>();
42
+            services.AddSingleton<ILuObjectConverterDescriptor<LuGroupDbo, LuGroups>, LuGroupsDboDescriptor>();
43
+            // DB Write
44
+
34 45
             services.AddLuObjectConverters();
35
-            
46
+            // DB read
47
+            services.AddLuObjectConverterPoco<LuObjectsMetadata, LuObjectsMetadataDbo>();
48
+            services.AddLuObjectConverterPoco<LuGroups, LuGroupDbo>();
49
+            // DB Write
50
+
51
+            // DB filter/orderBy
52
+            services.AddSingleton<ILuConvertersTypeConverter>(new LuConvertersTypeConverter(new Dictionary<Type, Type>
53
+            {
54
+                {typeof(LuGroupDbo), typeof(LuGroups)}
55
+            }));
56
+
36 57
             services.AddScoped<LuGroupsBusiness>();
37 58
 
59
+            services.AddLuOptions();
60
+            services.Configure<LuExpressionUtils.LuExpressionParserOptions>(options =>
61
+            {
62
+                options.ScriptOptions = options.ScriptOptions.AddReferences(typeof(Program).Assembly);
63
+            });
64
+
38 65
             services.AddDbContext<Luticate2DbContext>(options =>
39 66
             {
40 67
                 options.UseNpgsql(@"Host=localhost;Database=luticate2;Username=dev;Password=dev");
@@ -44,7 +71,7 @@ namespace Luticate2.Auth.ConsoleSample
44 71
             }, ServiceLifetime.Transient);
45 72
 
46 73
             ServiceProvider = services.BuildServiceProvider();
47
-            
74
+
48 75
             var loop = new Loop(typeof(CommandsEnum));
49 76
             loop.Execute();
50 77
         }

+ 7
- 1
Luticate2.Auth.Tests/Business/Pagination/LuFilterTests.cs 查看文件

@@ -1,7 +1,9 @@
1 1
 using Luticate2.Auth.Auth.Dbo;
2 2
 using Luticate2.Auth.Utils.Business.Pagination;
3
+using Luticate2.Auth.Utils.Business.Utils;
3 4
 using Luticate2.Auth.Utils.Dbo;
4 5
 using Luticate2.Auth.Utils.Dbo.Result;
6
+using Microsoft.CodeAnalysis.Scripting;
5 7
 using Xunit;
6 8
 
7 9
 namespace Luticate2.Auth.Tests.Business.Pagination
@@ -11,7 +13,11 @@ namespace Luticate2.Auth.Tests.Business.Pagination
11 13
         [Fact]
12 14
         public void Test1()
13 15
         {
14
-            var filterResult = LuFilterParser.Parse<LuGroupDbo>("x.Name.Contains(\"test\")");
16
+            var options = new LuExpressionUtils.LuExpressionParserOptions
17
+            {
18
+                ScriptOptions = ScriptOptions.Default.AddReferences(typeof(LuGroupDbo).Assembly)
19
+            };
20
+            var filterResult = LuFilterParser.Parse<LuGroupDbo>("x.Name.Contains(\"test\")", options);
15 21
             Assert.Equal(LuStatus.Success.ToInt(), filterResult.Status);
16 22
             Assert.NotNull(filterResult.Data);
17 23
         }

+ 2
- 2
Luticate2.Auth.Tests/DataAccess/Crud/LuEfCrudTests.cs 查看文件

@@ -131,7 +131,7 @@ namespace Luticate2.Auth.Tests.DataAccess.Crud
131 131
             {
132 132
                 Filter = new LuFilterDbo
133 133
                 {
134
-                    Expression = (Expression<Func<TableSimple1Dbo, bool>>) (x => true)
134
+                    Expression = (Expression<Func<TableSimple1Dbo, bool>>) (x => x.Name == "test1" || x.Name == "test2")
135 135
                 },
136 136
                 Page = 0,
137 137
                 OrderBy = new LuOrderByDbo
@@ -195,7 +195,7 @@ namespace Luticate2.Auth.Tests.DataAccess.Crud
195 195
             {
196 196
                 Filter = new LuFilterDbo
197 197
                 {
198
-                    Expression = (Expression<Func<TableSimple1Dbo, bool>>) (x => true)
198
+                    Expression = (Expression<Func<TableSimple1Dbo, bool>>) (x => x.Name == "test1" || x.Name == "test2")
199 199
                 },
200 200
                 Page = 0,
201 201
                 OrderBy = new LuOrderByDbo

+ 15
- 0
Luticate2.Auth/Auth/DataAccess/Converters/LuGroups.cs 查看文件

@@ -0,0 +1,15 @@
1
+using Luticate2.Auth.Auth.DataAccess.Models;
2
+using Luticate2.Auth.Auth.Dbo;
3
+using Luticate2.Auth.Utils.Business.Converters.ObjectConverterDescriptor;
4
+
5
+namespace Luticate2.Auth.Auth.DataAccess.Converters
6
+{
7
+    public class LuGroupsDboDescriptor : LuObjectConverterDescriptor<LuGroupDbo, LuGroups>
8
+    {
9
+        public LuGroupsDboDescriptor()
10
+        {
11
+            AddStaticMemberConverter(x => x.Metadata, y => y.IdNavigation);
12
+            AddStaticMemberConverter(x => x.Name, y => y.Name);
13
+        }
14
+    }
15
+}

+ 16
- 0
Luticate2.Auth/Auth/DataAccess/Converters/LuObjectsMetadata.cs 查看文件

@@ -0,0 +1,16 @@
1
+using Luticate2.Auth.Auth.DataAccess.Models;
2
+using Luticate2.Auth.Auth.Dbo;
3
+using Luticate2.Auth.Utils.Business.Converters.ObjectConverterDescriptor;
4
+
5
+namespace Luticate2.Auth.Auth.DataAccess.Converters
6
+{
7
+    public class LuObjectsMetadataDboDescriptor : LuObjectConverterDescriptor<LuObjectsMetadataDbo, LuObjectsMetadata>
8
+    {
9
+        public LuObjectsMetadataDboDescriptor()
10
+        {
11
+            AddStaticMemberConverter(x => x.Id, y => y.Id.ToString());
12
+            AddStaticMemberConverter(x => x.CreatedAt, y => y.CreatedAt);
13
+            AddStaticMemberConverter(x => x.UpdatedAt, y => y.UpdatedAt);
14
+        }
15
+    }
16
+}

+ 1
- 5
Luticate2.Auth/Auth/Dbo/LuObjectDbo.cs 查看文件

@@ -1,11 +1,7 @@
1
-using System;
2
-
3
-namespace Luticate2.Auth.Auth.Dbo
1
+namespace Luticate2.Auth.Auth.Dbo
4 2
 {
5 3
     public class LuObjectDbo
6 4
     {
7
-        public Guid Id { get; set; }
8
-        
9 5
         public LuObjectsMetadataDbo Metadata { get; set; }
10 6
     }
11 7
 }

+ 1
- 1
Luticate2.Auth/Auth/Dbo/LuObjectsMetadataDbo.cs 查看文件

@@ -4,7 +4,7 @@ namespace Luticate2.Auth.Auth.Dbo
4 4
 {
5 5
     public class LuObjectsMetadataDbo
6 6
     {
7
-        public Guid Id { get; set; }
7
+        public string Id { get; set; }
8 8
 
9 9
         public DateTime CreatedAt { get; set; }
10 10
 

+ 0
- 1
Luticate2.Auth/Luticate2.Auth.csproj 查看文件

@@ -3,7 +3,6 @@
3 3
     <TargetFramework>netcoreapp2.1</TargetFramework>
4 4
   </PropertyGroup>
5 5
   <ItemGroup>
6
-    <Folder Include="Auth\DataAccess\Converters" />
7 6
     <Folder Include="Utils\DataAccess" />
8 7
   </ItemGroup>
9 8
   <ItemGroup>

+ 1
- 1
Luticate2.Auth/Utils/Business/Converters/ExpressionConverter/LuExpressionConverterVisitor.cs 查看文件

@@ -136,7 +136,7 @@ namespace Luticate2.Auth.Utils.Business.Converters.ExpressionConverter
136 136
                 return LuResult<Expression>.Error(LuStatus.InternalError.ToInt(),
137 137
                     $"Converter descriptor lambda has incorrect number of arguments for {typeFrom} => {typeTo} => {methodCallExpression.Method}");
138 138
             }
139
-            if (valueExpression.Parameters[0].Type != typeTo)
139
+            if (typeTo != valueExpression.Parameters[0].Type && !valueExpression.Parameters[0].Type.IsAssignableFrom(typeTo))
140 140
             {
141 141
                 return LuResult<Expression>.Error(LuStatus.InternalError.ToInt(),
142 142
                     $"Invalid conversion lambda for {typeFrom} => {typeTo}");

+ 12
- 0
Luticate2.Auth/Utils/Business/Converters/LuConvertersExtensions.cs 查看文件

@@ -4,7 +4,9 @@ using System.Collections.ObjectModel;
4 4
 using System.Linq;
5 5
 using Luticate2.Auth.Utils.Business.Converters.ObjectConverter;
6 6
 using Luticate2.Auth.Utils.Business.Converters.ObjectConverterDescriptor;
7
+using Luticate2.Auth.Utils.Business.Utils;
7 8
 using Luticate2.Auth.Utils.Interfaces;
9
+using Microsoft.CodeAnalysis.Scripting;
8 10
 using Microsoft.Extensions.DependencyInjection;
9 11
 using Microsoft.Extensions.DependencyInjection.Extensions;
10 12
 
@@ -92,5 +94,15 @@ namespace Luticate2.Auth.Utils.Business.Converters
92 94
         {
93 95
             services.AddSingleton<ILuObjectConverter<TTypeFrom, TTypeTo>, LuObjectConverterPoco<TTypeFrom, TTypeTo>>();
94 96
         }
97
+
98
+        public static void AddLuOptions(this IServiceCollection services)
99
+        {
100
+            services.AddOptions<LuExpressionUtils.LuExpressionParserOptions>().Configure(options =>
101
+            {
102
+                options.ScriptOptions = ScriptOptions.Default
103
+                    .AddReferences(typeof(LuExpressionUtils.LuExpressionParserOptions).Assembly)
104
+                    .AddImports("System.Linq.Enumerable");
105
+            });
106
+        }
95 107
     }
96 108
 }

+ 5
- 1
Luticate2.Auth/Utils/Business/Converters/ObjectConverter/LuObjectConverterPoco.cs 查看文件

@@ -1,4 +1,5 @@
1 1
 using System;
2
+using System.Linq;
2 3
 using Luticate2.Auth.Utils.Business.Fields;
3 4
 using Luticate2.Auth.Utils.Business.Utils;
4 5
 using Luticate2.Auth.Utils.Dbo;
@@ -41,7 +42,10 @@ namespace Luticate2.Auth.Utils.Business.Converters.ObjectConverter
41 42
                     continue;
42 43
                 }
43 44
 
44
-                var subSrcPropExpressionResult = descriptor.GetMemberValueExpression(memberInfo, options.DescriptorOptions);
45
+                // TODO Hack to deal with inherited members; need to check if it is correct
46
+                var originalMemberInfo = memberInfo.DeclaringType.GetMember(memberInfo.Name).First();
47
+
48
+                var subSrcPropExpressionResult = descriptor.GetMemberValueExpression(originalMemberInfo, options.DescriptorOptions);
45 49
                 if (!subSrcPropExpressionResult)
46 50
                 {
47 51
                     return subSrcPropExpressionResult.To<object>();

+ 8
- 17
Luticate2.Auth/Utils/Business/Pagination/LuFilterParser.cs 查看文件

@@ -1,16 +1,13 @@
1
-using System;
2
-using System.Linq.Expressions;
1
+using Luticate2.Auth.Utils.Business.Utils;
3 2
 using Luticate2.Auth.Utils.Dbo;
4 3
 using Luticate2.Auth.Utils.Dbo.Pagination;
5 4
 using Luticate2.Auth.Utils.Dbo.Result;
6
-using Microsoft.CodeAnalysis.CSharp.Scripting;
7
-using Microsoft.CodeAnalysis.Scripting;
8 5
 
9 6
 namespace Luticate2.Auth.Utils.Business.Pagination
10 7
 {
11 8
     public class LuFilterParser
12 9
     {
13
-        public static LuResult<LuFilterDbo> Parse<T>(string data)
10
+        public static LuResult<LuFilterDbo> Parse<T>(string data, LuExpressionUtils.LuExpressionParserOptions options)
14 11
         {
15 12
             if (string.IsNullOrWhiteSpace(data))
16 13
             {
@@ -19,20 +16,14 @@ namespace Luticate2.Auth.Utils.Business.Pagination
19 16
                     Expression = null
20 17
                 });
21 18
             }
19
+
22 20
             var completeData = $"(x) => ({data})";
23
-            try
24
-            {
25
-                var options = ScriptOptions.Default.AddReferences(typeof(LuFilterParser).Assembly, typeof(Expression<>).Assembly);
26
-                var expr = CSharpScript.EvaluateAsync<Expression<Func<T, bool>>>(completeData, options).Result;
27
-                return LuResult<LuFilterDbo>.Ok(new LuFilterDbo
28
-                {
29
-                    Expression = expr
30
-                });
31
-            }
32
-            catch (Exception e)
21
+            var expressionResult = LuExpressionUtils.Parse<T, bool>(completeData, options);
22
+
23
+            return expressionResult.Select(expression => new LuFilterDbo
33 24
             {
34
-                return LuResult<LuFilterDbo>.Error(LuStatus.InputError.ToInt(), e, "Failed to parse filter expression");
35
-            }
25
+                Expression = expression
26
+            });
36 27
         }
37 28
     }
38 29
 }

+ 44
- 41
Luticate2.Auth/Utils/Business/Pagination/LuOrderByParser.cs 查看文件

@@ -1,5 +1,6 @@
1
-using System.Collections.Generic;
2
-using Luticate2.Auth.Utils.Dbo;
1
+using System;
2
+using System.Collections.Generic;
3
+using Luticate2.Auth.Utils.Business.Utils;
3 4
 using Luticate2.Auth.Utils.Dbo.Pagination;
4 5
 using Luticate2.Auth.Utils.Dbo.Result;
5 6
 
@@ -7,52 +8,54 @@ namespace Luticate2.Auth.Utils.Business.Pagination
7 8
 {
8 9
     public static class LuOrderByParser
9 10
     {
10
-        public static LuResult<LuOrderByDbo> Parse(string data)
11
+        public static LuResult<LuOrderByDbo> Parse<TDbo>(IEnumerable<string> data, LuExpressionUtils.LuExpressionParserOptions options)
11 12
         {
12
-            if (data == null)
13
+            var orderByDbo = new LuOrderByDbo
13 14
             {
14
-                data = "";
15
+                OrderByFields = new List<LuOrderByFieldDbo>()
16
+            };
17
+            foreach (var orderByFieldStr in data)
18
+            {
19
+                var orderByFieldResult = Parse<TDbo>(orderByFieldStr, options);
20
+                if (!orderByFieldResult)
21
+                {
22
+                    return orderByFieldResult.To<LuOrderByDbo>();
23
+                }
24
+                var orderByFieldDbo = orderByFieldResult.Data;
25
+
26
+                orderByDbo.OrderByFields.Add(orderByFieldDbo);
15 27
             }
16
-            data = data.Trim();
17
-            if (data != "")
28
+
29
+            return LuResult<LuOrderByDbo>.Ok(orderByDbo);
30
+        }
31
+
32
+        public static LuResult<LuOrderByFieldDbo> Parse<TDbo>(string data, LuExpressionUtils.LuExpressionParserOptions options)
33
+        {
34
+            var orderByFieldDbo = new LuOrderByFieldDbo();
35
+            if (data.EndsWith(":desc", StringComparison.OrdinalIgnoreCase))
18 36
             {
19
-                var dbo = new LuOrderByDbo {OrderByFields = new List<LuOrderByFieldDbo>()};
20
-                var fields = data.Split(',');
21
-                foreach (var field in fields)
37
+                orderByFieldDbo.Asc = false;
38
+                data = data.Substring(0, data.Length - 5);
39
+            }
40
+            else
41
+            {
42
+                orderByFieldDbo.Asc = true;
43
+
44
+                if (data.EndsWith(":asc", StringComparison.OrdinalIgnoreCase))
22 45
                 {
23
-                    if (field == "")
24
-                    {
25
-                        return LuResult<LuOrderByDbo>.Error(LuStatus.InputError.ToInt(),
26
-                            $"LuOrderByParser: {data}", "Empty order by field");
27
-                    }
28
-                    var orderByField = new LuOrderByFieldDbo();
29
-                    // TODO parse
30
-//                    var split = field.Split(':');
31
-//                    if (split.Length > 2 || split.Length == 0)
32
-//                    {
33
-//                        return LuResult<LuOrderByDbo>.Error(LuStatus.InputError.ToInt(),
34
-//                            $"LuOrderByParser: {data}", "Invalid order by field syntax");
35
-//                    }
36
-//                    orderByField.Field = LuFieldDbo.Make(split[0]);
37
-//                    var order = split.Length == 2 ? split[1].ToLower() : "asc";
38
-//                    if (order == "asc")
39
-//                    {
40
-//                        orderByField.Asc = true;
41
-//                    }
42
-//                    else if (order == "desc")
43
-//                    {
44
-//                        orderByField.Asc = false;
45
-//                    }
46
-//                    else
47
-//                    {
48
-//                        return LuResult<LuOrderByDbo>.Error(LuStatus.InputError.ToInt(),
49
-//                            $"LuOrderByParser: {data}", "Empty order by field order");
50
-//                    }
51
-                    dbo.OrderByFields.Add(orderByField);
46
+                    data = data.Substring(0, data.Length - 4);
52 47
                 }
53
-                return LuResult<LuOrderByDbo>.Ok(dbo);
54 48
             }
55
-            return LuResult<LuOrderByDbo>.Error(LuStatus.InputError.ToInt(), "Order by is empty or missing", "");
49
+
50
+            var completeData = $"(x) => ({data})";
51
+            var expressionResult = LuExpressionUtils.Parse<TDbo, object>(completeData, options);
52
+            if (!expressionResult)
53
+            {
54
+                return expressionResult.To<LuOrderByFieldDbo>();
55
+            }
56
+            orderByFieldDbo.Expression = expressionResult.Data;
57
+
58
+            return LuResult<LuOrderByFieldDbo>.Ok(orderByFieldDbo);
56 59
         }
57 60
     }
58 61
 }

+ 21
- 0
Luticate2.Auth/Utils/Business/Utils/LuExpressionUtils.cs 查看文件

@@ -5,11 +5,18 @@ using System.Linq.Expressions;
5 5
 using System.Reflection;
6 6
 using Luticate2.Auth.Utils.Dbo;
7 7
 using Luticate2.Auth.Utils.Dbo.Result;
8
+using Microsoft.CodeAnalysis.CSharp.Scripting;
9
+using Microsoft.CodeAnalysis.Scripting;
8 10
 
9 11
 namespace Luticate2.Auth.Utils.Business.Utils
10 12
 {
11 13
     public static class LuExpressionUtils
12 14
     {
15
+        public class LuExpressionParserOptions
16
+        {
17
+            public ScriptOptions ScriptOptions { get; set; }
18
+        }
19
+
13 20
         public static Expression GetFromConvert(Expression exp)
14 21
         {
15 22
             if (exp is LambdaExpression lambdaExpression)
@@ -166,5 +173,19 @@ namespace Luticate2.Auth.Utils.Business.Utils
166 173
 
167 174
             return null;
168 175
         }
176
+
177
+        public static LuResult<Expression<Func<TArg, TResult>>> Parse<TArg, TResult>(string data, LuExpressionParserOptions options)
178
+        {
179
+            try
180
+            {
181
+//                var options = ScriptOptions.Default.AddReferences(typeof(LuFilterParser).Assembly, typeof(Expression<>).Assembly);
182
+                var expr = CSharpScript.EvaluateAsync<Expression<Func<TArg, TResult>>>(data, options.ScriptOptions).Result;
183
+                return LuResult<Expression<Func<TArg, TResult>>>.Ok(expr);
184
+            }
185
+            catch (Exception e)
186
+            {
187
+                return LuResult<Expression<Func<TArg, TResult>>>.Error(LuStatus.InputError.ToInt(), e, "Failed to parse expression");
188
+            }
189
+        }
169 190
     }
170 191
 }

+ 26
- 37
Luticate2.Auth/Utils/DataAccess/Crud/LuEfCrudDataAccess.cs 查看文件

@@ -26,8 +26,8 @@ namespace Luticate2.Auth.Utils.DataAccess.Crud
26 26
         public LuEfCrudDataAccess(IServiceProvider serviceProvider)
27 27
         {
28 28
             ServiceProvider = serviceProvider;
29
-            ConvertersAllocator = ServiceProvider.GetRequiredService<ILuConvertersAllocator>();
30
-            ConvertersTypeConverter = ServiceProvider.GetRequiredService<ILuConvertersTypeConverter>();
29
+            ConvertersAllocator = ServiceProvider.GetRequiredService<ILuConvertersAllocator>(); // TODO Make a DbContext or DataAccess specific ILuConvertersAllocator (in case of multiple DbContext)
30
+            ConvertersTypeConverter = ServiceProvider.GetRequiredService<ILuConvertersTypeConverter>(); // TODO same as above
31 31
         }
32 32
 
33 33
         protected virtual LuConvertersOptions GetOptions()
@@ -37,7 +37,7 @@ namespace Luticate2.Auth.Utils.DataAccess.Crud
37 37
                 Allocator = ConvertersAllocator,
38 38
                 Parameters = new Dictionary<ParameterExpression, Expression>(),
39 39
                 TypeConverter = ConvertersTypeConverter
40
-            };// TODO
40
+            };
41 41
         }
42 42
 
43 43
         protected virtual LuResult<TModel> ConvertDboToModel(LuPartialFieldsDbo partialInput, TDbo dbo)
@@ -114,63 +114,49 @@ namespace Luticate2.Auth.Utils.DataAccess.Crud
114 114
                 return LuResult<IQueryable<TModel>>.Ok(queryable);
115 115
             }
116 116
 
117
-            var lamdbaDbo = (Expression<Func<TDbo, bool>>) filter.Expression;
117
+            var lambdaDbo = (Expression<Func<TDbo, bool>>) filter.Expression;
118 118
 
119 119
             var options = GetOptions();
120 120
             var converter = new LuExpressionConverterVisitor(options, ServiceProvider);
121
-            var lamdbaModel = converter.Visit(lamdbaDbo) as Expression<Func<TModel, bool>>;// TODO Handle errors
122
-            return LuResult<IQueryable<TModel>>.Ok(queryable.Where(lamdbaModel));
121
+            var lambdaModel = converter.Visit(lambdaDbo) as Expression<Func<TModel, bool>>;// TODO Handle errors
122
+            return LuResult<IQueryable<TModel>>.Ok(queryable.Where(lambdaModel));
123 123
         }
124 124
 
125 125
         protected virtual LuResult<IQueryable<TModel>> OrderByField(LuOrderByFieldDbo orderByField, IQueryable<TModel> queryable)
126 126
         {
127
-            var lamdbaDbo = (Expression<Func<TDbo, object>>) orderByField.Expression;
127
+            var lambdaDbo = (Expression<Func<TDbo, object>>) orderByField.Expression;
128 128
 
129 129
             var options = GetOptions();
130 130
             var converter = new LuExpressionConverterVisitor(options, ServiceProvider);
131
-            var lamdbaModel = converter.Visit(lamdbaDbo) as Expression<Func<TModel, object>>;
131
+            var lambdaModelNoConvert = converter.Visit(lambdaDbo) as LambdaExpression;// TODO Handle errors
132
+            var lambdaModel = Expression.Lambda<Func<TModel, object>>(lambdaModelNoConvert.Body, lambdaModelNoConvert.Parameters);
132 133
 
133
-            IOrderedQueryable<TModel> ordered = null;
134
+            IOrderedQueryable<TModel> ordered;
134 135
 
135 136
             if (queryable is IOrderedQueryable<TModel> orderedQueryable)
136 137
             {
137 138
                 if (orderByField.Asc)
138 139
                 {
139
-                    ordered = orderedQueryable.ThenBy(lamdbaModel);
140
+                    ordered = orderedQueryable.ThenBy(lambdaModel);
140 141
                 }
141 142
                 else
142 143
                 {
143
-                    ordered = orderedQueryable.ThenByDescending(lamdbaModel);
144
+                    ordered = orderedQueryable.ThenByDescending(lambdaModel);
144 145
                 }
145 146
             }
146 147
             else
147 148
             {
148 149
                 if (orderByField.Asc)
149 150
                 {
150
-                    ordered = queryable.OrderBy(lamdbaModel);
151
+                    ordered = queryable.OrderBy(lambdaModel);
151 152
                 }
152 153
                 else
153 154
                 {
154
-                    ordered = queryable.OrderByDescending(lamdbaModel);
155
+                    ordered = queryable.OrderByDescending(lambdaModel);
155 156
                 }
156 157
             }
157 158
 
158 159
             return LuResult<IQueryable<TModel>>.Ok(ordered);
159
-
160
-//            var expressionBuilder = ServiceProvider.GetService<ILuDboModelExpressionConverter<TDbo, TModel>>();
161
-//            var expressionResult = expressionBuilder.ConvertLamdba<TModel>(orderByfield.);
162
-//            if (!expressionResult)
163
-//            {
164
-//                return expressionResult.To<IQueryable<TModel>>();
165
-//            }
166
-//
167
-//            var expression = expressionResult.Data;
168
-//            var expressionNoConvert = LuExpressionUtils.GetFromConvert(expression);
169
-//
170
-//            var ordered = queryable.OrderBy(expressionNoConvert);
171
-//
172
-//            return LuResult<IQueryable<TModel>>.Ok(ordered);
173
-//            return LuResult<IQueryable<TModel>>.Ok(queryable);
174 160
         }
175 161
 
176 162
         protected virtual LuResult<IQueryable<TModel>> OrderBy(LuOrderByDbo orderBy, IQueryable<TModel> queryable)
@@ -210,7 +196,6 @@ namespace Luticate2.Auth.Utils.DataAccess.Crud
210 196
                 {
211 197
                     return includeResult.To<LuPaginatedDbo<TDbo>>();
212 198
                 }
213
-
214 199
                 var included = includeResult.Data;
215 200
 
216 201
                 var orderByResult = OrderBy(paginationParams.OrderBy, included);
@@ -218,7 +203,6 @@ namespace Luticate2.Auth.Utils.DataAccess.Crud
218 203
                 {
219 204
                     return orderByResult.To<LuPaginatedDbo<TDbo>>();
220 205
                 }
221
-
222 206
                 var ordered = orderByResult.Data;
223 207
                 
224 208
                 var filteredResult = Filter(paginationParams.Filter, ordered);
@@ -226,7 +210,6 @@ namespace Luticate2.Auth.Utils.DataAccess.Crud
226 210
                 {
227 211
                     return filteredResult.To<LuPaginatedDbo<TDbo>>();
228 212
                 }
229
-
230 213
                 var filtered = filteredResult.Data;
231 214
                 var count = filtered.Count();
232 215
 
@@ -235,19 +218,25 @@ namespace Luticate2.Auth.Utils.DataAccess.Crud
235 218
                 {
236 219
                     return paginatedResult.To<LuPaginatedDbo<TDbo>>();
237 220
                 }
238
-
239 221
                 var paginated = paginatedResult.Data;
240 222
 
241
-                var data = paginated.AsEnumerable().Select(model =>
223
+                var dboList = new List<TDbo>();
224
+                foreach (var model in paginated)
225
+                {
226
+                    var dboResult = ConvertModelToDbo(partialResponse, model);
227
+                    if (!dboResult)
242 228
                     {
243
-                        var convertResult = ConvertModelToDbo(partialResponse, model); // TODO Handle error
244
-                        return convertResult.Data;
245
-                    }).ToList();
229
+                        return dboResult.To<LuPaginatedDbo<TDbo>>();
230
+                    }
231
+                    var dbo = dboResult.Data;
232
+
233
+                    dboList.Add(dbo);
234
+                }
246 235
 
247 236
                 return LuResult<LuPaginatedDbo<TDbo>>.Ok(new LuPaginatedDbo<TDbo>
248 237
                 {
249 238
                     Count = count,
250
-                    Data = data
239
+                    Data = dboList
251 240
                 });
252 241
             });
253 242
             return result;

+ 1
- 1
Luticate2.Auth/Utils/Dbo/Pagination/LuPaginatedDbo.cs 查看文件

@@ -6,6 +6,6 @@ namespace Luticate2.Auth.Utils.Dbo.Pagination
6 6
     {
7 7
         public long Count { get; set; }
8 8
 
9
-        public List<TDbo> Data { get; set; }
9
+        public IList<TDbo> Data { get; set; }
10 10
     }
11 11
 }

Loading…
取消
儲存