| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 | using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Luticate2.Auth.Dbo;
using Luticate2.Auth.Dbo.Result;
namespace Luticate2.Auth.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<Func<TType1, TType3>> AddConvert<TType1, TType2, TType3>(Expression<Func<TType1, TType2>> exp)
        {
            var converted = Expression.Convert(exp, typeof(object));
            var expLambda = Expression.Lambda<Func<TType1, TType3>>(converted, exp.Parameters);
            return expLambda;
        }
        public static LuResult<TProperty> SetValueFromExpression<TDbo, TProperty>(Expression<Func<TDbo, TProperty>> 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<TProperty>.Ok(value);
                    case MemberTypes.Property:
                        ((PropertyInfo) memberInfo).SetValue(dboTo, value);
                        return LuResult<TProperty>.Ok(value);
                    default:
                        return LuResult<TProperty>.Error(LuStatus.InternalError.ToInt(),
                            $"Bad MemberType: {memberInfo.MemberType}");
                }
            }
            return LuResult<TProperty>.Error(LuStatus.InternalError.ToInt(), "Bad member expression");
        }
        public static LuResult<TProperty> GetValueFromExpression<TDbo, TProperty>(Expression<Func<TDbo, TProperty>> 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<TProperty>.Ok(value);
                    case MemberTypes.Property:
                        value = (TProperty) ((PropertyInfo) memberInfo).GetValue(dboTo);
                        return LuResult<TProperty>.Ok(value);
                    default:
                        return LuResult<TProperty>.Error(LuStatus.InternalError.ToInt(),
                            $"Bad MemberType: {memberInfo.MemberType}");
                }
            }
            return LuResult<TProperty>.Error(LuStatus.InternalError.ToInt(), "Bad member expression");
        }
        public static MemberInfo GetSingleMemberFromExpression(LambdaExpression property)
        {
            var memberExpression = GetFromConvert(property) as MemberExpression;
            if (memberExpression != null &&
                (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)
        {
            var methodCallExpression = GetFromConvert(method) as MethodCallExpression;
            // TODO check if something like methodCallExpression.Method.DeclaringType == method.Parameters.First().Type is usefull/required (static/extension methods)
            if (methodCallExpression != null &&
                (methodCallExpression.Object == method.Parameters.First() || methodCallExpression.Object == null))
            {
                return methodCallExpression.Method;
            }
            return null;
        }
        private static bool GetMembersFromExpression<TTypeTo, TProperty>(
            Expression<Func<TTypeTo, TProperty>> property, IList<MemberInfo> 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<Func<TTypeTo, object>>(memberExpression.Expression, property.Parameters);
                    var res = GetMembersFromExpression(exp, memberInfos);
                    if (res)
                    {
                        memberInfos.Add(memberExpression.Member);
                    }
                    return res;
                }
            }
            return false;
        }
        public static IList<MemberInfo> GetMembersFromExpression<TTypeTo, TProperty>(Expression<Func<TTypeTo, TProperty>> property)
        {
            var list = new List<MemberInfo>();
            if (GetMembersFromExpression(property, list))
            {
                return list;
            }
            return null;
        }
    }
}
 |