Ver código fonte

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 5 anos atrás
pai
commit
316f06c4f9

+ 1
- 1
Luticate2.Auth.ConsoleSample/Commands/CreateCommand.cs Ver arquivo

63
                 {
63
                 {
64
                     if (OutputType == "specific")
64
                     if (OutputType == "specific")
65
                     {
65
                     {
66
-                        Console.WriteLine($"{item.Id} {item.Name ?? "??"}");
66
+                        Console.WriteLine($"{item.Metadata.Id} {item.Name ?? "??"}");
67
                     }
67
                     }
68
                     else if (OutputType == "json-full")
68
                     else if (OutputType == "json-full")
69
                     {
69
                     {

+ 9
- 5
Luticate2.Auth.ConsoleSample/Commands/ListCommand.cs Ver arquivo

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

+ 30
- 3
Luticate2.Auth.ConsoleSample/Program.cs Ver arquivo

1
 using System;
1
 using System;
2
+using System.Collections.Generic;
2
 using Luticate2.Auth.Auth.Business;
3
 using Luticate2.Auth.Auth.Business;
3
 using Luticate2.Auth.Auth.DataAccess;
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
 using Luticate2.Auth.ConsoleSample.Commands;
8
 using Luticate2.Auth.ConsoleSample.Commands;
5
 using Luticate2.Auth.Utils.Business.Converters;
9
 using Luticate2.Auth.Utils.Business.Converters;
10
+using Luticate2.Auth.Utils.Business.Utils;
11
+using Luticate2.Auth.Utils.Interfaces;
6
 using Microsoft.EntityFrameworkCore;
12
 using Microsoft.EntityFrameworkCore;
7
 using Microsoft.Extensions.DependencyInjection;
13
 using Microsoft.Extensions.DependencyInjection;
8
 using NClap.Metadata;
14
 using NClap.Metadata;
21
         [Command(typeof(ExitCommand), Description = "Exits the shell")]
27
         [Command(typeof(ExitCommand), Description = "Exits the shell")]
22
         Exit
28
         Exit
23
     }
29
     }
24
-    
30
+
25
     class Program
31
     class Program
26
     {
32
     {
27
         public static IServiceProvider ServiceProvider;
33
         public static IServiceProvider ServiceProvider;
31
             IServiceCollection services = new ServiceCollection();
37
             IServiceCollection services = new ServiceCollection();
32
 
38
 
33
             services.AddLuObjectConverterDescriptors();
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
             services.AddLuObjectConverters();
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
             services.AddScoped<LuGroupsBusiness>();
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
             services.AddDbContext<Luticate2DbContext>(options =>
65
             services.AddDbContext<Luticate2DbContext>(options =>
39
             {
66
             {
40
                 options.UseNpgsql(@"Host=localhost;Database=luticate2;Username=dev;Password=dev");
67
                 options.UseNpgsql(@"Host=localhost;Database=luticate2;Username=dev;Password=dev");
44
             }, ServiceLifetime.Transient);
71
             }, ServiceLifetime.Transient);
45
 
72
 
46
             ServiceProvider = services.BuildServiceProvider();
73
             ServiceProvider = services.BuildServiceProvider();
47
-            
74
+
48
             var loop = new Loop(typeof(CommandsEnum));
75
             var loop = new Loop(typeof(CommandsEnum));
49
             loop.Execute();
76
             loop.Execute();
50
         }
77
         }

+ 7
- 1
Luticate2.Auth.Tests/Business/Pagination/LuFilterTests.cs Ver arquivo

1
 using Luticate2.Auth.Auth.Dbo;
1
 using Luticate2.Auth.Auth.Dbo;
2
 using Luticate2.Auth.Utils.Business.Pagination;
2
 using Luticate2.Auth.Utils.Business.Pagination;
3
+using Luticate2.Auth.Utils.Business.Utils;
3
 using Luticate2.Auth.Utils.Dbo;
4
 using Luticate2.Auth.Utils.Dbo;
4
 using Luticate2.Auth.Utils.Dbo.Result;
5
 using Luticate2.Auth.Utils.Dbo.Result;
6
+using Microsoft.CodeAnalysis.Scripting;
5
 using Xunit;
7
 using Xunit;
6
 
8
 
7
 namespace Luticate2.Auth.Tests.Business.Pagination
9
 namespace Luticate2.Auth.Tests.Business.Pagination
11
         [Fact]
13
         [Fact]
12
         public void Test1()
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
             Assert.Equal(LuStatus.Success.ToInt(), filterResult.Status);
21
             Assert.Equal(LuStatus.Success.ToInt(), filterResult.Status);
16
             Assert.NotNull(filterResult.Data);
22
             Assert.NotNull(filterResult.Data);
17
         }
23
         }

+ 2
- 2
Luticate2.Auth.Tests/DataAccess/Crud/LuEfCrudTests.cs Ver arquivo

131
             {
131
             {
132
                 Filter = new LuFilterDbo
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
                 Page = 0,
136
                 Page = 0,
137
                 OrderBy = new LuOrderByDbo
137
                 OrderBy = new LuOrderByDbo
195
             {
195
             {
196
                 Filter = new LuFilterDbo
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
                 Page = 0,
200
                 Page = 0,
201
                 OrderBy = new LuOrderByDbo
201
                 OrderBy = new LuOrderByDbo

+ 15
- 0
Luticate2.Auth/Auth/DataAccess/Converters/LuGroups.cs Ver arquivo

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 Ver arquivo

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 Ver arquivo

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

+ 1
- 1
Luticate2.Auth/Auth/Dbo/LuObjectsMetadataDbo.cs Ver arquivo

4
 {
4
 {
5
     public class LuObjectsMetadataDbo
5
     public class LuObjectsMetadataDbo
6
     {
6
     {
7
-        public Guid Id { get; set; }
7
+        public string Id { get; set; }
8
 
8
 
9
         public DateTime CreatedAt { get; set; }
9
         public DateTime CreatedAt { get; set; }
10
 
10
 

+ 0
- 1
Luticate2.Auth/Luticate2.Auth.csproj Ver arquivo

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

+ 1
- 1
Luticate2.Auth/Utils/Business/Converters/ExpressionConverter/LuExpressionConverterVisitor.cs Ver arquivo

136
                 return LuResult<Expression>.Error(LuStatus.InternalError.ToInt(),
136
                 return LuResult<Expression>.Error(LuStatus.InternalError.ToInt(),
137
                     $"Converter descriptor lambda has incorrect number of arguments for {typeFrom} => {typeTo} => {methodCallExpression.Method}");
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
                 return LuResult<Expression>.Error(LuStatus.InternalError.ToInt(),
141
                 return LuResult<Expression>.Error(LuStatus.InternalError.ToInt(),
142
                     $"Invalid conversion lambda for {typeFrom} => {typeTo}");
142
                     $"Invalid conversion lambda for {typeFrom} => {typeTo}");

+ 12
- 0
Luticate2.Auth/Utils/Business/Converters/LuConvertersExtensions.cs Ver arquivo

4
 using System.Linq;
4
 using System.Linq;
5
 using Luticate2.Auth.Utils.Business.Converters.ObjectConverter;
5
 using Luticate2.Auth.Utils.Business.Converters.ObjectConverter;
6
 using Luticate2.Auth.Utils.Business.Converters.ObjectConverterDescriptor;
6
 using Luticate2.Auth.Utils.Business.Converters.ObjectConverterDescriptor;
7
+using Luticate2.Auth.Utils.Business.Utils;
7
 using Luticate2.Auth.Utils.Interfaces;
8
 using Luticate2.Auth.Utils.Interfaces;
9
+using Microsoft.CodeAnalysis.Scripting;
8
 using Microsoft.Extensions.DependencyInjection;
10
 using Microsoft.Extensions.DependencyInjection;
9
 using Microsoft.Extensions.DependencyInjection.Extensions;
11
 using Microsoft.Extensions.DependencyInjection.Extensions;
10
 
12
 
92
         {
94
         {
93
             services.AddSingleton<ILuObjectConverter<TTypeFrom, TTypeTo>, LuObjectConverterPoco<TTypeFrom, TTypeTo>>();
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 Ver arquivo

1
 using System;
1
 using System;
2
+using System.Linq;
2
 using Luticate2.Auth.Utils.Business.Fields;
3
 using Luticate2.Auth.Utils.Business.Fields;
3
 using Luticate2.Auth.Utils.Business.Utils;
4
 using Luticate2.Auth.Utils.Business.Utils;
4
 using Luticate2.Auth.Utils.Dbo;
5
 using Luticate2.Auth.Utils.Dbo;
41
                     continue;
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
                 if (!subSrcPropExpressionResult)
49
                 if (!subSrcPropExpressionResult)
46
                 {
50
                 {
47
                     return subSrcPropExpressionResult.To<object>();
51
                     return subSrcPropExpressionResult.To<object>();

+ 8
- 17
Luticate2.Auth/Utils/Business/Pagination/LuFilterParser.cs Ver arquivo

1
-using System;
2
-using System.Linq.Expressions;
1
+using Luticate2.Auth.Utils.Business.Utils;
3
 using Luticate2.Auth.Utils.Dbo;
2
 using Luticate2.Auth.Utils.Dbo;
4
 using Luticate2.Auth.Utils.Dbo.Pagination;
3
 using Luticate2.Auth.Utils.Dbo.Pagination;
5
 using Luticate2.Auth.Utils.Dbo.Result;
4
 using Luticate2.Auth.Utils.Dbo.Result;
6
-using Microsoft.CodeAnalysis.CSharp.Scripting;
7
-using Microsoft.CodeAnalysis.Scripting;
8
 
5
 
9
 namespace Luticate2.Auth.Utils.Business.Pagination
6
 namespace Luticate2.Auth.Utils.Business.Pagination
10
 {
7
 {
11
     public class LuFilterParser
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
             if (string.IsNullOrWhiteSpace(data))
12
             if (string.IsNullOrWhiteSpace(data))
16
             {
13
             {
19
                     Expression = null
16
                     Expression = null
20
                 });
17
                 });
21
             }
18
             }
19
+
22
             var completeData = $"(x) => ({data})";
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 Ver arquivo

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
 using Luticate2.Auth.Utils.Dbo.Pagination;
4
 using Luticate2.Auth.Utils.Dbo.Pagination;
4
 using Luticate2.Auth.Utils.Dbo.Result;
5
 using Luticate2.Auth.Utils.Dbo.Result;
5
 
6
 
7
 {
8
 {
8
     public static class LuOrderByParser
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 Ver arquivo

5
 using System.Reflection;
5
 using System.Reflection;
6
 using Luticate2.Auth.Utils.Dbo;
6
 using Luticate2.Auth.Utils.Dbo;
7
 using Luticate2.Auth.Utils.Dbo.Result;
7
 using Luticate2.Auth.Utils.Dbo.Result;
8
+using Microsoft.CodeAnalysis.CSharp.Scripting;
9
+using Microsoft.CodeAnalysis.Scripting;
8
 
10
 
9
 namespace Luticate2.Auth.Utils.Business.Utils
11
 namespace Luticate2.Auth.Utils.Business.Utils
10
 {
12
 {
11
     public static class LuExpressionUtils
13
     public static class LuExpressionUtils
12
     {
14
     {
15
+        public class LuExpressionParserOptions
16
+        {
17
+            public ScriptOptions ScriptOptions { get; set; }
18
+        }
19
+
13
         public static Expression GetFromConvert(Expression exp)
20
         public static Expression GetFromConvert(Expression exp)
14
         {
21
         {
15
             if (exp is LambdaExpression lambdaExpression)
22
             if (exp is LambdaExpression lambdaExpression)
166
 
173
 
167
             return null;
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 Ver arquivo

26
         public LuEfCrudDataAccess(IServiceProvider serviceProvider)
26
         public LuEfCrudDataAccess(IServiceProvider serviceProvider)
27
         {
27
         {
28
             ServiceProvider = serviceProvider;
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
         protected virtual LuConvertersOptions GetOptions()
33
         protected virtual LuConvertersOptions GetOptions()
37
                 Allocator = ConvertersAllocator,
37
                 Allocator = ConvertersAllocator,
38
                 Parameters = new Dictionary<ParameterExpression, Expression>(),
38
                 Parameters = new Dictionary<ParameterExpression, Expression>(),
39
                 TypeConverter = ConvertersTypeConverter
39
                 TypeConverter = ConvertersTypeConverter
40
-            };// TODO
40
+            };
41
         }
41
         }
42
 
42
 
43
         protected virtual LuResult<TModel> ConvertDboToModel(LuPartialFieldsDbo partialInput, TDbo dbo)
43
         protected virtual LuResult<TModel> ConvertDboToModel(LuPartialFieldsDbo partialInput, TDbo dbo)
114
                 return LuResult<IQueryable<TModel>>.Ok(queryable);
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
             var options = GetOptions();
119
             var options = GetOptions();
120
             var converter = new LuExpressionConverterVisitor(options, ServiceProvider);
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
         protected virtual LuResult<IQueryable<TModel>> OrderByField(LuOrderByFieldDbo orderByField, IQueryable<TModel> queryable)
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
             var options = GetOptions();
129
             var options = GetOptions();
130
             var converter = new LuExpressionConverterVisitor(options, ServiceProvider);
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
             if (queryable is IOrderedQueryable<TModel> orderedQueryable)
136
             if (queryable is IOrderedQueryable<TModel> orderedQueryable)
136
             {
137
             {
137
                 if (orderByField.Asc)
138
                 if (orderByField.Asc)
138
                 {
139
                 {
139
-                    ordered = orderedQueryable.ThenBy(lamdbaModel);
140
+                    ordered = orderedQueryable.ThenBy(lambdaModel);
140
                 }
141
                 }
141
                 else
142
                 else
142
                 {
143
                 {
143
-                    ordered = orderedQueryable.ThenByDescending(lamdbaModel);
144
+                    ordered = orderedQueryable.ThenByDescending(lambdaModel);
144
                 }
145
                 }
145
             }
146
             }
146
             else
147
             else
147
             {
148
             {
148
                 if (orderByField.Asc)
149
                 if (orderByField.Asc)
149
                 {
150
                 {
150
-                    ordered = queryable.OrderBy(lamdbaModel);
151
+                    ordered = queryable.OrderBy(lambdaModel);
151
                 }
152
                 }
152
                 else
153
                 else
153
                 {
154
                 {
154
-                    ordered = queryable.OrderByDescending(lamdbaModel);
155
+                    ordered = queryable.OrderByDescending(lambdaModel);
155
                 }
156
                 }
156
             }
157
             }
157
 
158
 
158
             return LuResult<IQueryable<TModel>>.Ok(ordered);
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
         protected virtual LuResult<IQueryable<TModel>> OrderBy(LuOrderByDbo orderBy, IQueryable<TModel> queryable)
162
         protected virtual LuResult<IQueryable<TModel>> OrderBy(LuOrderByDbo orderBy, IQueryable<TModel> queryable)
210
                 {
196
                 {
211
                     return includeResult.To<LuPaginatedDbo<TDbo>>();
197
                     return includeResult.To<LuPaginatedDbo<TDbo>>();
212
                 }
198
                 }
213
-
214
                 var included = includeResult.Data;
199
                 var included = includeResult.Data;
215
 
200
 
216
                 var orderByResult = OrderBy(paginationParams.OrderBy, included);
201
                 var orderByResult = OrderBy(paginationParams.OrderBy, included);
218
                 {
203
                 {
219
                     return orderByResult.To<LuPaginatedDbo<TDbo>>();
204
                     return orderByResult.To<LuPaginatedDbo<TDbo>>();
220
                 }
205
                 }
221
-
222
                 var ordered = orderByResult.Data;
206
                 var ordered = orderByResult.Data;
223
                 
207
                 
224
                 var filteredResult = Filter(paginationParams.Filter, ordered);
208
                 var filteredResult = Filter(paginationParams.Filter, ordered);
226
                 {
210
                 {
227
                     return filteredResult.To<LuPaginatedDbo<TDbo>>();
211
                     return filteredResult.To<LuPaginatedDbo<TDbo>>();
228
                 }
212
                 }
229
-
230
                 var filtered = filteredResult.Data;
213
                 var filtered = filteredResult.Data;
231
                 var count = filtered.Count();
214
                 var count = filtered.Count();
232
 
215
 
235
                 {
218
                 {
236
                     return paginatedResult.To<LuPaginatedDbo<TDbo>>();
219
                     return paginatedResult.To<LuPaginatedDbo<TDbo>>();
237
                 }
220
                 }
238
-
239
                 var paginated = paginatedResult.Data;
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
                 return LuResult<LuPaginatedDbo<TDbo>>.Ok(new LuPaginatedDbo<TDbo>
236
                 return LuResult<LuPaginatedDbo<TDbo>>.Ok(new LuPaginatedDbo<TDbo>
248
                 {
237
                 {
249
                     Count = count,
238
                     Count = count,
250
-                    Data = data
239
+                    Data = dboList
251
                 });
240
                 });
252
             });
241
             });
253
             return result;
242
             return result;

+ 1
- 1
Luticate2.Auth/Utils/Dbo/Pagination/LuPaginatedDbo.cs Ver arquivo

6
     {
6
     {
7
         public long Count { get; set; }
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
 }

Carregando…
Cancelar
Salvar