using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using Luticate2.Auth.Utils.Dbo; using Luticate2.Auth.Utils.Dbo.Result; namespace Luticate2.Auth.Utils.Business { public static class LuExpressionUtils { public static Expression GetFromConvert(Expression exp) { Expression e = exp; if (exp is LambdaExpression lambdaExpression) { e = lambdaExpression.Body; } Expression operand; if ((e.NodeType == ExpressionType.Convert || e.NodeType == ExpressionType.ConvertChecked) && e is UnaryExpression) { operand = ((UnaryExpression) e).Operand; } else { operand = e; } return operand; } public static Expression> AddConvert(Expression> exp) { var converted = Expression.Convert(exp, typeof(object)); var expLambda = Expression.Lambda>(converted, exp.Parameters); return expLambda; } public static LuResult SetValueFromExpression(Expression> property, TDbo dboTo, TProperty value) { var memberInfo = GetSingleMemberFromExpression(property); if (memberInfo != null) { switch (memberInfo.MemberType) { case MemberTypes.Field: ((FieldInfo) memberInfo).SetValue(dboTo, value); return LuResult.Ok(value); case MemberTypes.Property: ((PropertyInfo) memberInfo).SetValue(dboTo, value); return LuResult.Ok(value); default: return LuResult.Error(LuStatus.InternalError.ToInt(), $"Bad MemberType: {memberInfo.MemberType}"); } } return LuResult.Error(LuStatus.InternalError.ToInt(), "Bad member expression"); } public static LuResult GetValueFromExpression(Expression> property, TDbo dboTo) { var memberInfo = GetSingleMemberFromExpression(property); if (memberInfo != null) { TProperty value; switch (memberInfo.MemberType) { case MemberTypes.Field: value = (TProperty) ((FieldInfo) memberInfo).GetValue(dboTo); return LuResult.Ok(value); case MemberTypes.Property: value = (TProperty) ((PropertyInfo) memberInfo).GetValue(dboTo); return LuResult.Ok(value); default: return LuResult.Error(LuStatus.InternalError.ToInt(), $"Bad MemberType: {memberInfo.MemberType}"); } } return LuResult.Error(LuStatus.InternalError.ToInt(), "Bad member expression"); } public static MemberInfo GetSingleMemberFromExpression(LambdaExpression property) { if (GetFromConvert(property) is MemberExpression memberExpression && (memberExpression.Expression == property.Parameters.First() || (memberExpression.Expression == null && memberExpression.Member.DeclaringType == property.Parameters.First().Type))) { return memberExpression.Member; } return null; } public static MethodInfo GetSingleMethodFromExpression(LambdaExpression method) { // TODO check if something like methodCallExpression.Method.DeclaringType == method.Parameters.First().Type is usefull/required (static/extension methods) if (GetFromConvert(method) is MethodCallExpression methodCallExpression && (methodCallExpression.Object == method.Parameters.First() || methodCallExpression.Object == null)) { return methodCallExpression.Method; } return null; } private static bool GetMembersFromExpression( Expression> property, IList memberInfos) { MemberExpression memberExpression; if ((property.Body.NodeType == ExpressionType.Convert || property.Body.NodeType == ExpressionType.ConvertChecked) && property.Body is UnaryExpression) { memberExpression = ((UnaryExpression) property.Body).Operand as MemberExpression; } else { memberExpression = property.Body as MemberExpression; } if (memberExpression != null) { if (memberExpression.Expression == property.Parameters.First()) { memberInfos.Add(memberExpression.Member); return true; } else if (memberExpression.Expression is MemberExpression) { var exp = Expression.Lambda>(memberExpression.Expression, property.Parameters); var res = GetMembersFromExpression(exp, memberInfos); if (res) { memberInfos.Add(memberExpression.Member); } return res; } } return false; } public static IList GetMembersFromExpression(Expression> property) { var list = new List(); if (GetMembersFromExpression(property, list)) { return list; } return null; } } }