diff --git a/Mf.Razor.Entity/Interfaces/IServiceLocator.cs b/Mf.Razor.Entity/Interfaces/IServiceLocator.cs index d5ae5bd..f734d74 100644 --- a/Mf.Razor.Entity/Interfaces/IServiceLocator.cs +++ b/Mf.Razor.Entity/Interfaces/IServiceLocator.cs @@ -8,6 +8,5 @@ namespace Mf.Razor.Entity.Interfaces { public interface IServiceLocator { - } } diff --git a/Mf.Razor.Entity/Mf.Razor.Entity.csproj b/Mf.Razor.Entity/Mf.Razor.Entity.csproj index 237d661..037ba6e 100644 --- a/Mf.Razor.Entity/Mf.Razor.Entity.csproj +++ b/Mf.Razor.Entity/Mf.Razor.Entity.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/Mf.Razor.Entity/Services/FluentQuery.cs b/Mf.Razor.Entity/Services/FluentQuery.cs new file mode 100644 index 0000000..9937bfb --- /dev/null +++ b/Mf.Razor.Entity/Services/FluentQuery.cs @@ -0,0 +1,231 @@ +using System.Linq.Expressions; +using System.Net.Http.Headers; +using System.Net.Http.Json; +using Mf.Core.SubEntities.QueryModel; + +namespace Mf.Razor.Entity.Services; + +public class FluentQuery + { + private HttpClient httpClient; + + public FluentQuery(HttpClient httpClient) + { + this.httpClient = httpClient; + } + private readonly QueryRequest _request = new(); + + public FluentQuery Include(Expression> expression) + { + var propName = GetPropertyPath(expression.Body); + _request.Includes.Add(propName); + return this; + } + + public void Clear() + { + _request.Filters = new(); + _request.Includes = new(); + _request.Take = null; + _request.Skip = null; + _request.ObjectType = null; + + } + + public FluentQuery Where(Expression> expression) + { + if (expression.Body is BinaryExpression binary) + { + var left = GetPropertyName((MemberExpression)binary.Left); + var op = GetOperator(binary.NodeType); + var right = Expression.Lambda(binary.Right).Compile().DynamicInvoke()?.ToString(); + + _request.Filters.Add(new Filter + { + Field = left, + Operator = op, + Value = right + }); + } + else if (expression.Body is MethodCallExpression methodCall) + { + var method = methodCall.Method.Name; + + if (method is "Contains" or "StartsWith" or "EndsWith") + { + var field = GetPropertyName(methodCall.Object ?? methodCall.Arguments[0]); + var value = Expression.Lambda(methodCall.Arguments[^1]).Compile().DynamicInvoke()?.ToString(); + + _request.Filters.Add(new Filter + { + Field = field, + Operator = method, // توی سرور بررسی کن با این نام یا تبدیل کن + Value = value + }); + } + else + { + throw new NotSupportedException($"Unsupported method: {method}"); + } + } + + + + + + return this; + } + + public FluentQuery Skip(int count) + { + _request.Skip = count; + return this; + } + + public FluentQuery Take(int count) + { + _request.Take = count; + return this; + } + + + + public QueryRequest Build() => _request; + + public async Task PostAsync(string token) + { + try + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + _request.ObjectType = typeof(T).AssemblyQualifiedName; + var result = await httpClient.PostAsJsonAsync("api/generic/get", _request); + return result; + } + catch (Exception ex) + { + return new HttpResponseMessage(); + } + finally + { + Clear(); + } + + + } + + public async Task> ResultPostAsync(string token) + { + try + { + var result = await PostAsync(token); + //var ssss = await result.Content.ReadFromJsonAsync>(); + if (result != null && await result.Content.ReadFromJsonAsync>() is List rr) + { + return rr; + } + } + catch (Exception ex) + { + //ServiceLocator.Log($"Error read from api {ex.Message}"); + } + return new List(); + } + + + public async Task InsertAsync(T model,string token) + { + try + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + AlterRequest req = new AlterRequest() { Model = model, ObjectType = typeof(T).AssemblyQualifiedName }; + return await httpClient.PostAsJsonAsync("api/generic/insert", req); + } + finally + { + + Clear(); + } + + } + + + public async Task UpdateAsync(T model,string token) + { + try + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + AlterRequest req = new AlterRequest() { Model = model, ObjectType = typeof(T).AssemblyQualifiedName }; + return await httpClient.PostAsJsonAsync("api/generic/update", req); + } + finally + { + Clear(); + } + + } + + public async Task DeleteAsync(T model,string token) + { + try + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + AlterRequest req = new AlterRequest() { Model = model, ObjectType = typeof(T).AssemblyQualifiedName }; + return await httpClient.PostAsJsonAsync("api/generic/delete", req); + } + finally + { + Clear(); + } + + } + + + + private string GetOperator(ExpressionType type) + { + return type switch + { + ExpressionType.Equal => "=", + ExpressionType.GreaterThan => ">", + ExpressionType.GreaterThanOrEqual => ">=", + ExpressionType.LessThan => "<", + ExpressionType.LessThanOrEqual => "<=", + ExpressionType.NotEqual => "!=", + _ => throw new NotSupportedException("Unsupported operator") + }; + } + + + + private string GetPropertyName(Expression expression) + { + return expression switch + { + MemberExpression me => me.Member.Name, + UnaryExpression ue when ue.Operand is MemberExpression me => me.Member.Name, + _ => throw new NotSupportedException("Unsupported expression") + }; + } + + + private string GetPropertyPath(Expression expression) + { + if (expression is UnaryExpression unaryExpr && unaryExpr.Operand is MemberExpression) + { + expression = unaryExpr.Operand; + } + + var members = new Stack(); + + while (expression is MemberExpression member) + { + members.Push(member.Member.Name); + expression = member.Expression; + } + + return string.Join(".", members); + } + + + } + diff --git a/Mf.Razor.Entity/Services/RouteConfig.cs b/Mf.Razor.Entity/Services/RouteConfig.cs new file mode 100644 index 0000000..ce93b4b --- /dev/null +++ b/Mf.Razor.Entity/Services/RouteConfig.cs @@ -0,0 +1,10 @@ +namespace Mf.Razor.Entity.Services; + +public class RouteConfig +{ + public string GenericApiGetRequest { get; set; } + public string GenericApiGetItemRequest { get; set; } + public string GenericApiDeleteRequest { get; set; } + public string GenericApiUpdateRequest { get; set; } + public string GenericApiCreateRequest { get; set; } +} \ No newline at end of file