using System; using System.Collections.Generic; using System.Linq.Expressions; using Luticate2.Auth.Business.Fields.DMEC; using Luticate2.Auth.Dbo; using Luticate2.Auth.Dbo.Result; using Luticate2.Auth.Exceptions; using Luticate2.Auth.Interfaces; namespace Luticate2.Auth.Business.Fields { public class LuExpressionConverterVisitor : ExpressionVisitor { public LuExpressionConverterOptions Options { get; } protected IServiceProvider ServiceProvider { get; } public LuExpressionConverterVisitor(LuExpressionConverterOptions options, IServiceProvider serviceProvider) { Options = options; ServiceProvider = serviceProvider; } protected LuResult> StackSimpleExpression(Expression expression, Stack stack) { if (expression is ParameterExpression parameterExpression) { stack.Push(parameterExpression); return LuResult>.Ok(stack); } else if (expression is MemberExpression memberExpression) { stack.Push(memberExpression); var result = StackSimpleExpression(memberExpression.Expression, stack); return result; } else if (expression is MethodCallExpression methodCallExpression) { if (methodCallExpression.Object != null) { stack.Push(methodCallExpression); var result = StackSimpleExpression(methodCallExpression.Object, stack); return result; } else { stack.Push(methodCallExpression); var param = Expression.Parameter(typeof(LuExpressionConverterStaticMethods)); stack.Push(param); return LuResult>.Ok(stack); } } return LuResult>.Error(LuStatus.InternalError.ToInt(), "Invalid Simple Expression Member"); } protected Expression ReplaceExpression(Expression expression) { var stackResult = StackSimpleExpression(expression, new Stack()).ThrowIfNotSuccess(); var firstResult = stackResult.Data.Peek(); var type = typeof(ILuExpressionConverter<>); var gtype = type.MakeGenericType(firstResult.Type); var converter = (ILuExpressionConverter) ServiceProvider.GetService(gtype); if (converter == null) { LuResult.Error(LuStatus.InternalError.ToInt(), $"Could not get service: ILuExpressionConverter<{firstResult.Type.Name}>").Throw(); } var exp = converter.ConvertExpression(stackResult.Data, null, Options).ThrowIfNotSuccess(); return exp.Data; } protected override Expression VisitMember(MemberExpression node) { return ReplaceExpression(node); } protected override Expression VisitMethodCall(MethodCallExpression node) { return ReplaceExpression(node); } } }