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); }
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); }
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); }
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)); }
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); }
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); }
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); }
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); } }
public abstract (Expression Expression, ExpressionConversionResult ExpressionConversionResult) Convert(T node, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal = false, params Type[] genericArguments);
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]));
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); }
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); }