Пример #1
0
        public override (System.Linq.Expressions.Expression, ExpressionConversionResult) Convert(ArrowFunctionExpression arrowFunctionExpression, ExpressionConverterContext context, ExpressionConverterScope scope, bool allowTerminal, params Type[] genericArguments)
        {
            var argumentGenericTypeMap = arrowFunctionExpression.Params.Zip(genericArguments, (param, genericType) => new { Param = param, GenericType = genericType }).ToArray();
            var parameterExpressions   = argumentGenericTypeMap.Select(tuple => System.Linq.Expressions.Expression.Parameter(tuple.GenericType.ResolveGenericType(scope.GenericTypeResolutionMap), tuple.Param.As <Identifier>().Name)).ToArray();

            var lambdaScope = new ExpressionConverterScope(scope, null)
            {
                Variables = parameterExpressions.ToDictionary(parameterExpression => parameterExpression.Name, parameterExpression => (System.Linq.Expressions.Expression)parameterExpression)
            };

            var bodyExpression = context.ExpressionConverterResolver.Convert(arrowFunctionExpression.Body, context, lambdaScope, false);
            var returnType     = bodyExpression.Type;

            if (scope.TargetType.IsGenericType && typeof(Expression <>) == scope.TargetType.GetGenericTypeDefinition())
            {
                return(System.Linq.Expressions.Expression.Constant(System.Linq.Expressions.Expression.Lambda(bodyExpression, parameterExpressions)), DefaultResult);
            }
            else
            {
                scope.TargetType.GetGenericArguments().Last().GenericAssignableFrom(returnType, scope.GenericTypeResolutionMap);
                var returnTargetType = scope.TargetType.GetGenericArguments().Last().ResolveGenericType(scope.GenericTypeResolutionMap);
                //if (returnTargetType.IsAssignableFrom(bodyExpression.Type) && bodyExpression.Type != returnTargetType)
                //{
                //	bodyExpression = System.Linq.Expressions.Expression.Convert(bodyExpression, returnTargetType);
                //}
                var lambdaMethodInfo = ExpressionHelper.ExtractGenericDefinitionMethodInfo <System.Linq.Expressions.Expression, Func <System.Linq.Expressions.Expression, ParameterExpression[], Expression <Func <int> > > >(_ => System.Linq.Expressions.Expression.Lambda <Func <int> >);
                var genericType      = Type.GetType($"System.Func`{arrowFunctionExpression.Params.Count + 1}");
                var funcType         = genericType.MakeGenericType(parameterExpressions.Select(p => p.Type).Concat(new[] { returnTargetType }).ToArray());
                var expression       = lambdaMethodInfo.MakeGenericMethod(funcType).Invoke(null, new object[] { bodyExpression, parameterExpressions });
                return((System.Linq.Expressions.Expression)expression, DefaultResult);
                //lambdaMethodInfo.MakeGenericMethod()
                //return System.Linq.Expressions.Expression.Lambda(bodyExpression, parameterExpressions);
            }
        }
Пример #2
0
        public override (Expression, ExpressionConversionResult) Convert(ArrayExpression node, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal, params Type[] genericArguments)
        {
            if (expressionConverterScope.TargetType == typeof(JArray))
            {
                var code = expressionConverterContext.Source.Substring(node.Range.Start, node.Range.End - node.Range.Start + 1);
                using (var reader = new StringReader(code)) {
                    var @object = JsonSerializer.Deserialize(reader, expressionConverterScope.TargetType);
                    return(Expression.Constant(@object), DefaultResult);
                }
            }
            var targetType = expressionConverterScope.TargetType != null?expressionConverterScope.TargetType.GetEnumerableUnderlyingType() : null;

            var itemScope           = new ExpressionConverterScope(expressionConverterScope, targetType);
            var elementsExpressions = node.Elements.Select((element, index) => {
                var itemExpression = expressionConverterContext.ExpressionConverterResolver.Convert(element, expressionConverterContext, itemScope, allowTerminal);
                if (index == 0 && targetType == null)
                {
                    targetType = itemExpression.Type;
                }
                if (itemExpression.Type != targetType && targetType != null)
                {
                    itemExpression = Expression.Convert(itemExpression, targetType);
                }
                return(itemExpression);
            }).ToArray();

            return(Expression.NewArrayInit(targetType, elementsExpressions), DefaultResult);
        }
Пример #3
0
 public ExpressionConverterScope(ExpressionConverterScope parent, Type targetType)
 {
     Parent     = parent;
     TargetType = targetType;
     GenericTypeResolutionMap = parent != null ? new Dictionary <Type, Type>(parent.GenericTypeResolutionMap) : new Dictionary <Type, Type>();
     Variables = new Dictionary <string, Expression>();
 }
Пример #4
0
        public override (System.Linq.Expressions.Expression, ExpressionConversionResult) Convert(BinaryExpression node, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal, params Type[] genericArguments)
        {
            var leftOperand  = expressionConverterContext.ExpressionConverterResolver.Convert(node.Left, expressionConverterContext, new ExpressionConverterScope(expressionConverterScope, null), allowTerminal);
            var rightOperand = expressionConverterContext.ExpressionConverterResolver.Convert(node.Right, expressionConverterContext, new ExpressionConverterScope(expressionConverterScope, null), allowTerminal);

            if (rightOperand.Type != leftOperand.Type)
            {
                rightOperand = System.Linq.Expressions.Expression.Convert(rightOperand, leftOperand.Type);
            }
            return(System.Linq.Expressions.Expression.MakeBinary(BinaryOperatorMap[node.Operator], leftOperand, rightOperand), DefaultResult);
        }
Пример #5
0
        public override (System.Linq.Expressions.Expression, ExpressionConversionResult) Convert(Literal literal, ExpressionConverterContext context, ExpressionConverterScope scope, bool allowTerminal, params Type[] genericArguments)
        {
            if (literal.Value is string && !(scope.TargetType == typeof(string)))
            {
                using (var reader = new StringReader($"'{(string)literal.Value}'")) {
                    var @object = JsonSerializer.Deserialize(reader, scope.TargetType);
                    return(System.Linq.Expressions.Expression.Constant(@object), DefaultResult);
                }
            }
            var expression = (System.Linq.Expressions.Expression)System.Linq.Expressions.Expression.Constant(literal.Value);

            if (scope.TargetType != null && !scope.TargetType.IsGenericParameter && !scope.TargetType.IsGenericType && !scope.TargetType.IsAssignableFrom(expression.Type) && literal.Value != null)
            {
                expression = System.Linq.Expressions.Expression.Convert(expression, scope.TargetType);
            }
            return(expression, DefaultResult);
        }
Пример #6
0
        public override (LinqExpressions.Expression, ExpressionConversionResult) Convert(Esprima.Ast.Identifier identifier, ExpressionConverterContext context, ExpressionConverterScope scope, bool allowTerminal, params Type[] genericArguments)
        {
            var value = scope.FindIdentifier(identifier.Name);

            return(value, DefaultResult);
        }
 public System.Linq.Expressions.Expression Convert(INode node, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal)
 {
     return(FindExpressionConverter(node).Convert(node, expressionConverterContext, expressionConverterScope, allowTerminal));
 }
Пример #8
0
        public override (System.Linq.Expressions.Expression, ExpressionConversionResult) Convert(Esprima.Ast.MemberExpression memberExpression, ExpressionConverterContext context, ExpressionConverterScope scope, bool allowTerminal, params Type[] genericArguments)
        {
            var objectExpression   = context.ExpressionConverterResolver.Convert(memberExpression.Object, context, scope, true);
            var propertyIdentifier = memberExpression.Property.As <Identifier>();
            var propertyInfo       = objectExpression.Type.GetProperty(propertyIdentifier.Name) ?? objectExpression.Type.GetProperty(propertyIdentifier.Name.ToPascalCase());

            if (propertyInfo == null)
            {
                throw new Exception($"Unable to find property ${propertyIdentifier.Name} on type ${objectExpression.Type.Name}");
            }
            if (!context.IsAdmin)
            {
                var ruleMap = context.RuleMapRegistry.GetRuleMap(objectExpression.Type, context.securityContext);
                if (ruleMap == null)
                {
                    throw new UnauthorizedAccessException($"You do not have access to type { objectExpression.Type }.");
                }
                var typePermission = (bool?)ruleMap.ResolveTypeCustom(Permission.Read, context.securityContext);
                var hasInstancePermissionResolverExpression = ruleMap.HasAnyInstancePermissionResolverExpression;
                var propertyPermission = (bool?)ruleMap.ResolvePropertyCustom(Permission.Read, propertyInfo, context.securityContext);
                var shouldFilter       = ruleMap.ShouldFilterForProperty(propertyInfo, context.securityContext);
                var hasInstancePropertyPermissionResolverExpression = ruleMap.HasAnyInstancePropertyPermissionResolverExpression(propertyInfo, Permission.Read);

                var result = new ExpressionConversionResult()
                {
                    ShouldApplyFilter     = shouldFilter,
                    ShouldApplyProjection = true
                };

                //var hasAccess = typePermission == null && (hasInstancePermissionResolverExpression || (propertyPermission.HasValue && propertyPermission.Value) || hasInstancePropertyPermissionResolverExpression);
                //hasAccess = hasAccess || (typePermission.Value && !(propertyPermission.HasValue && !propertyPermission.Value));
                //hasAccess = hasAccess || (!typePermission.Value && (hasInstancePermissionResolverExpression || (propertyPermission.HasValue && propertyPermission.Value) || hasInstancePropertyPermissionResolverExpression));
                //hasAccess = hasAccess || (!hasInstancePermissionResolverExpression && ((propertyPermission.HasValue && propertyPermission.Value) || hasInstancePropertyPermissionResolverExpression));
                //hasAccess = hasAccess || (hasInstancePermissionResolverExpression && !(propertyPermission.HasValue && !propertyPermission.Value));
                //hasAccess = hasAccess || (!propertyPermission.HasValue && hasInstancePropertyPermissionResolverExpression);

                var hasAccess = ruleMap.PropertiesDefaultPermission == Permission.Read;


                var propertyAccessExpression = (System.Linq.Expressions.Expression)System.Linq.Expressions.Expression.MakeMemberAccess(objectExpression, propertyInfo);
                if (hasInstancePropertyPermissionResolverExpression)
                {
                    var instancePropertyPermissionExpression = ruleMap.ResolveInstancePropertyCustomResolverExpression(propertyInfo, Permission.Read, context.securityContext, objectExpression);
                    var predicateExpression = instancePropertyPermissionExpression;
                    if (predicateExpression != null && predicateExpression.Type != typeof(bool))
                    {
                        predicateExpression = System.Linq.Expressions.Expression.Convert(predicateExpression, typeof(bool));
                    }
                    propertyAccessExpression = System.Linq.Expressions.Expression.Condition(predicateExpression, propertyAccessExpression, System.Linq.Expressions.Expression.Default(propertyInfo.PropertyType));
                }

                if (!context.IsAdmin && !hasAccess)
                {
                    throw new UnauthorizedAccessException($"You do not have access to property {propertyInfo.Name} on type { objectExpression.Type }.");
                }
                return(propertyAccessExpression, result);
            }
            return((System.Linq.Expressions.Expression)System.Linq.Expressions.Expression.MakeMemberAccess(objectExpression, propertyInfo), DefaultResult);
        }
Пример #9
0
        public override (Expression, ExpressionConversionResult) Convert(Esprima.Ast.ConditionalExpression node, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal, params Type[] genericArguments)
        {
            var condition = expressionConverterContext.ExpressionConverterResolver.Convert(node.Test, expressionConverterContext, expressionConverterScope, allowTerminal);
            var left      = expressionConverterContext.ExpressionConverterResolver.Convert(node.Consequent, expressionConverterContext, expressionConverterScope, allowTerminal);
            var right     = expressionConverterContext.ExpressionConverterResolver.Convert(node.Alternate, expressionConverterContext, expressionConverterScope, allowTerminal);

            return(Expression.Condition(condition, left, right), DefaultResult);
        }
Пример #10
0
        Expression IExpressionConverter.Convert(Esprima.Ast.INode expression, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal, params Type[] genericArguments)
        {
            var(resultExpression, result) = Convert((T)expression, expressionConverterContext, expressionConverterScope, allowTerminal, genericArguments);
            if (!expressionConverterContext.IsAdmin && resultExpression != null && typeof(IEnumerable).IsAssignableFrom(resultExpression.Type) && typeof(string) != resultExpression.Type)
            {
                var underlyingType = resultExpression.Type.GetEnumerableUnderlyingType();
                var rule           = expressionConverterContext.RuleMapRegistry.GetRuleMap(underlyingType, expressionConverterContext.securityContext);
                if (rule != null && result.ShouldApplyFilter)
                {
                    var parameterExpression  = Expression.Parameter(underlyingType);
                    var permissionExpression = rule.GetInstanceCustomResolverExpression(expressionConverterContext.securityContext, parameterExpression, Permission.Read);
                    if (permissionExpression != null && permissionExpression.Type != typeof(bool))
                    {
                        permissionExpression = Expression.Convert(permissionExpression, typeof(bool));
                    }
                    if (permissionExpression != null)
                    {
                        var predicateExpression = permissionExpression;
                        var predicateLambda     = Expression.Lambda(predicateExpression, parameterExpression);
                        resultExpression = typeof(IQueryable).IsAssignableFrom(resultExpression.Type) ?
                                           Expression.Call(QueryableWhereMethodInfo.MakeGenericMethod(underlyingType), resultExpression, predicateLambda)
                                                : Expression.Call(EnumerableWhereMethodInfo.MakeGenericMethod(underlyingType), resultExpression, predicateLambda);
                    }
                }
            }
            var ruleMap = expressionConverterContext.RuleMapRegistry.GetRuleMap(resultExpression.Type, expressionConverterContext.securityContext);

            if (false && !expressionConverterContext.IsAdmin && ruleMap != null && !allowTerminal && ruleMap.RequireProjection && result.ShouldApplyProjection)
            {
                resultExpression = ruleMap.GetDefaultProjectionExpression(expressionConverterContext.securityContext, resultExpression, expressionConverterContext.RuleMaps);
            }
            return(resultExpression);
        }
Пример #11
0
 public abstract (Expression Expression, ExpressionConversionResult ExpressionConversionResult) Convert(T node, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal = false, params Type[] genericArguments);
Пример #12
0
        protected (MethodInfo MethodInfo, Expression[] Arguments, ExpressionConversionResult ExpressionConversionResult) FindMethodInfo(MethodInfo[] methodInfosCandidates, Esprima.Ast.INode[] arguments, ExpressionConverterContext context, ExpressionConverterScope scope, Expression instanceExpression = null, bool isExtension = false)
        {
            MethodInfo methodInfo = null;

            Expression[] argumentsExpressions = null;
            ExpressionConversionResult expressionConversionResult = new ExpressionConversionResult();
            Permission?permission = Permission.None;
            var        methodInfoCandidateIndex = 0;

            while (methodInfo == null && methodInfoCandidateIndex < methodInfosCandidates.Length)
            {
                var methodInfoCandidate         = methodInfosCandidates[methodInfoCandidateIndex];
                var methodParameters            = methodInfoCandidate.GetParameters();
                var argumentParameterMap        = methodParameters.Skip(isExtension ? 1 : 0).Zip(arguments, (parameterInfo, argument) => (parameterInfo, argument: (Esprima.Ast.INode)argument)).ToArray();
                var parameterArgumentTupleIndex = 0;
                var isValid = true;
                var methodInfoCandidateArgumentsExpressions = new List <Expression>();
                if (isExtension)
                {
                    var instanceParameter = methodParameters.First();
                    isValid = instanceParameter.ParameterType.IsGenericType ? instanceParameter.ParameterType.GenericAssignableFrom(instanceExpression.Type, scope.GenericTypeResolutionMap) : instanceParameter.ParameterType.IsAssignableFrom(instanceExpression.Type);
                }
                while (isValid && parameterArgumentTupleIndex < argumentParameterMap.Length)
                {
                    var tuple     = argumentParameterMap[parameterArgumentTupleIndex];
                    var converter = context.ExpressionConverterResolver.FindExpressionConverter(tuple.argument);
                    if (converter.IsGenericType)
                    {
                        var argumentGenericType = converter.GetGenericType(tuple.argument, tuple.parameterInfo.ParameterType);
                        if ((isValid = AreGenericDefinitionEqual(tuple.parameterInfo.ParameterType, argumentGenericType)))
                        {
                            var nodes                  = converter.GetRequiredGenericArgumentIndices(tuple.argument, tuple.parameterInfo.ParameterType);
                            var parameterType          = tuple.parameterInfo.ParameterType;
                            var inputGenericArguments  = new List <(IEnumerable <int> path, Type Type)>();
                            var outputGenericArguments = new List <(IEnumerable <int> path, Type Type)>();
                            foreach (var node in nodes)
                            {
                                var stack = new Stack <(TypeNode, Type)>();
                                stack.Push((node, parameterType));
                                while (stack.Any())
                                {
                                    var currentNode          = stack.Pop();
                                    var nodeGenericArguments = currentNode.Item2.GetGenericArguments();
                                    if (currentNode.Item1.Children.Any())
                                    {
                                        foreach (var child in currentNode.Item1.Children)
                                        {
                                            stack.Push((child, nodeGenericArguments[currentNode.Item1.Index]));
Пример #13
0
        public override (Expression Expression, ExpressionConversionResult ExpressionConversionResult) Convert(Esprima.Ast.CallExpression methodCallExpression, ExpressionConverterContext context, ExpressionConverterScope scope, bool allowTerminal, params Type[] genericArguments)
        {
            var memberExpression = methodCallExpression.Callee as Esprima.Ast.MemberExpression;

            Esprima.Ast.Identifier methodIdentifier = null;
            if (memberExpression != null)
            {
                methodIdentifier = (Esprima.Ast.Identifier)memberExpression.Property;
            }
            else
            {
                methodIdentifier = (Esprima.Ast.Identifier)methodCallExpression.Callee;
            }
            var        arguments              = methodCallExpression.Arguments.Cast <Esprima.Ast.INode>().ToArray();
            MethodInfo methodInfo             = null;
            Expression instanceExpression     = null;
            Expression instanceExpressionDump = null;

            Expression[] argumentsExpressions = null;
            ExpressionConversionResult expressionConversionResult = null;

            if (memberExpression == null)
            {
                //method is static
                (methodInfo, argumentsExpressions, expressionConversionResult) = FindMethodInfo(context.StaticMethods.FindMethodInfos(methodIdentifier.Name, arguments.Count()).ToArray(), arguments, context, scope);
            }
            else
            {
                //method is not static
                instanceExpression = instanceExpressionDump = context.ExpressionConverterResolver.Convert(memberExpression.Object, context, scope, true);
                var instanceType          = instanceExpression.Type;
                var methodInfosCandidates = instanceType.GetMethods().FindMethodInfos(methodIdentifier.Name, arguments.Length);
                (methodInfo, argumentsExpressions, expressionConversionResult) = FindMethodInfo(methodInfosCandidates, arguments, context, scope, instanceExpression);

                if (methodInfo == null)
                {
                    //try extension methods
                    methodInfosCandidates = context.ExtensionMethods.FindMethodInfos(methodIdentifier.Name, arguments.Length + 1);
                    (methodInfo, argumentsExpressions, expressionConversionResult) = FindMethodInfo(methodInfosCandidates, arguments, context, scope, instanceExpression, true);
                    if (methodInfo != null)
                    {
                        argumentsExpressions = new Expression[] { instanceExpression }.Concat(argumentsExpressions).ToArray();
                        instanceExpression   = null;
                    }
                }
            }
            if (methodInfo == null)
            {
                //Fallback on custom converters
                var customConverter = context.CustomMethodCallExpressionConverters.FirstOrDefault(converter => converter.CanHandle(methodCallExpression, context, scope, allowTerminal, genericArguments));
                if (customConverter != null)
                {
                    return(customConverter.Convert(methodCallExpression, context, scope, allowTerminal, genericArguments));
                }
                throw new NotImplementedException($"Method {methodIdentifier.Name} on type {instanceExpressionDump.Type} not found.");
            }
            var callExpressiom = Expression.Call(instanceExpression, methodInfo, argumentsExpressions);

            return(callExpressiom, expressionConversionResult);
        }
        public override (Expression, ExpressionConversionResult) Convert(Esprima.Ast.ObjectExpression objectExpression, ExpressionConverterContext context, ExpressionConverterScope scope, bool allowTerminal, params Type[] genericArguments)
        {
            if (scope.TargetType != null)
            {
                var code = context.Source.Substring(objectExpression.Range.Start, objectExpression.Range.End - objectExpression.Range.Start + 1);
                using (var reader = new StringReader(code)) {
                    var @object = JsonSerializer.Deserialize(reader, scope.TargetType);
                    return(Expression.Constant(@object), DefaultResult);
                }
            }
            var propertyValueExpressions = objectExpression.Properties.Select(property => new {
                Property        = property,
                ValueExpression = context.ExpressionConverterResolver.Convert(property.Value, context, scope, false)
            }).ToArray();
            var  tuples        = propertyValueExpressions.Select(propertyValueExpression => new Tuple <Type, string>(propertyValueExpression.ValueExpression.Type, ((Esprima.Ast.Identifier)propertyValueExpression.Property.Key).Name)).ToArray();
            var  set           = new HashSet <Tuple <Type, string> >(tuples);
            Type anonymousType = null;

            if (!Cache.TryGetValue(set, out anonymousType))
            {
                anonymousType = AnonymousTypeBuilder.BuildAnonymousType(set);
                Cache[set]    = anonymousType;
            }
            var newExpression            = Expression.New(anonymousType.GetConstructor(new Type[0]));
            var initializationExpression = Expression.MemberInit(
                newExpression,
                propertyValueExpressions.Select(pve => Expression.Bind(anonymousType.GetProperty(((Esprima.Ast.Identifier)pve.Property.Key).Name), pve.ValueExpression))
                );

            return(initializationExpression, DefaultResult);
        }
Пример #15
0
        public override (System.Linq.Expressions.Expression, ExpressionConversionResult) Convert(UnaryExpression node, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal, params Type[] genericArguments)
        {
            var operand = expressionConverterContext.ExpressionConverterResolver.Convert(node.Argument, expressionConverterContext, expressionConverterScope, allowTerminal);

            return(System.Linq.Expressions.Expression.MakeUnary(UnaryOperatorMap[node.Operator], operand, expressionConverterScope.TargetType), DefaultResult);
        }