| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 | using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Luticate2.Auth.Utils.Business.ExpressionConverter;
using Luticate2.Auth.Utils.Business.Utils;
using Luticate2.Auth.Utils.Interfaces;
namespace Luticate2.Auth.Utils.Business.ObjectConverterDescriptor
{
    public class LuObjectConverterDescriptor : ILuObjectConverterDescriptor
    {
        protected enum PropertyType
        {
            Value,
            Object
        }
        protected class LuObjectConverterDescriptorMemberInfo
        {
            public LambdaExpression ValueExpression { get; set; }
            public PropertyType PropertyType { get; set; }
        }
        protected class LuObjectConverterDescriptorMethodInfo
        {
            public LambdaExpression ValueExpression { get; set; }
        }
        protected delegate LuObjectConverterDescriptorMethodInfo DynamicMethodConverter(MethodInfo methodInfo, IDictionary<Type, Type> types);
        private IDictionary<MemberInfo, LuObjectConverterDescriptorMemberInfo> StaticMemberConverters { get; } = new Dictionary<MemberInfo, LuObjectConverterDescriptorMemberInfo>();
        private IDictionary<MethodInfo, LuObjectConverterDescriptorMethodInfo> StaticMethodConverters { get; } = new Dictionary<MethodInfo, LuObjectConverterDescriptorMethodInfo>();
        private IDictionary<MethodInfo, DynamicMethodConverter> DynamicMethodConverters { get; } = new Dictionary<MethodInfo, DynamicMethodConverter>();
        protected void AddMemberConverter(LambdaExpression memberFrom, LambdaExpression valueExpression, PropertyType propertyType)
        {
            // TODO: check memberInfo != null
            var memberInfo = LuExpressionUtils.GetSingleMemberFromExpression(memberFrom);
            StaticMemberConverters.Add(memberInfo, new LuObjectConverterDescriptorMemberInfo
            {
                ValueExpression = LuExpressionUtils.GetFromConvert(valueExpression),
                PropertyType = propertyType
            });
        }
        protected void AddStaticMethodConverter(LambdaExpression methodFrom, LambdaExpression valueExpression)
        {
            // TODO: check methodInfo != null
            var methodInfo = LuExpressionUtils.GetSingleMethodFromExpression(methodFrom);
            StaticMethodConverters.Add(methodInfo, new LuObjectConverterDescriptorMethodInfo
            {
                ValueExpression = LuExpressionUtils.GetFromConvert(valueExpression)
            });
        }
        protected void AddDynamicMethodConverter(LambdaExpression methodFrom, DynamicMethodConverter converter)
        {
            // TODO: check methodInfo != null
            var methodInfo = LuExpressionUtils.GetSingleMethodFromExpression(methodFrom);
            var genericMethodInfo = methodInfo.GetGenericMethodDefinition();
            DynamicMethodConverters.Add(genericMethodInfo, converter);
        }
        protected void AddDynamicMethodConverterTemplate(LambdaExpression methodFrom)
        {
            AddDynamicMethodConverter(methodFrom,
                (info, types) =>
                {
                    var genericMethodInfo = info.GetGenericMethodDefinition();
                    var templateMethodInfo = genericMethodInfo.MakeGenericMethod(info.GetGenericArguments().Select(x => types[x]).ToArray());
                    var lambdaParams = new List<ParameterExpression>
                    {
                        Expression.Parameter(templateMethodInfo.DeclaringType) // TODO what if DeclaringType is static class
                    };
                    var methodParams = templateMethodInfo.GetParameters().Select(x => Expression.Parameter(x.ParameterType)).ToList();
                    lambdaParams.AddRange(methodParams);
                    var methodCallExpression = Expression.Call(templateMethodInfo.IsStatic ? null : lambdaParams[0], templateMethodInfo, methodParams);
                    var body = LuExpressionUtils.GetFromConvert(methodCallExpression);
                    var lambda = Expression.Lambda(body, lambdaParams);
                    return new LuObjectConverterDescriptorMethodInfo
                    {
                        ValueExpression = lambda
                    };
                }
            );
        }
        public LambdaExpression GetMemberValueExpression(MemberInfo memberInfo, LuExpressionConverterOptions options)
        {
            if (StaticMemberConverters.ContainsKey(memberInfo))
            {
                return StaticMemberConverters[memberInfo].ValueExpression;
            }
            return null;
        }
        public LambdaExpression GetMethodValueExpression(MethodInfo methodInfo, LuExpressionConverterOptions options)
        {
            if (StaticMethodConverters.ContainsKey(methodInfo))
            {
                return StaticMethodConverters[methodInfo].ValueExpression;
            }
            var genericMethodInfo = methodInfo.GetGenericMethodDefinition();
            if (DynamicMethodConverters.ContainsKey(genericMethodInfo))
            {
                var result = DynamicMethodConverters[genericMethodInfo](methodInfo, options.Types);
                if (result != null)
                {
                    return result.ValueExpression;
                }
            }
            return null;
        }
    }
    public class LuObjectConverterDescriptor<TTypeFrom, TTypeTo> : LuObjectConverterDescriptor, ILuObjectConverterDescriptor<TTypeFrom, TTypeTo>
    {
        protected void AddMemberConverter(Expression<Func<TTypeFrom, object>> memberFrom,
            Expression<Func<TTypeTo, object>> valueExpression, PropertyType propertyType)
        {
            AddMemberConverter((LambdaExpression) memberFrom, valueExpression, propertyType);
        }
        protected void AddNullMemberConverter(Expression<Func<TTypeFrom, object>> memberFrom)
        {
            AddMemberConverter(memberFrom, to => default(TTypeTo), PropertyType.Value);
        }
    }
}
 |