Exemple #1
0
        public Expression <BindingDelegate> CompileToDelegate(
            CastedExpressionBindingProperty expression, DataContextStack dataContext)
        {
            var expr = BindingCompiler.ReplaceParameters(expression.Expression, dataContext);

            expr = new ExpressionNullPropagationVisitor(e => true).Visit(expr);
            expr = ExpressionUtils.ConvertToObject(expr);
            return(Expression.Lambda <BindingDelegate>(expr, BindingCompiler.ViewModelsParameter, BindingCompiler.CurrentControlParameter));
        }
 public override void VisitPropertyBinding(ResolvedPropertyBinding propertyBinding)
 {
     if (BindingCompiler != null)
     {
         // try to compile bindings to see errors
         try
         {
             BindingCompiler.PrecompileBinding(propertyBinding.Binding, "id123", propertyBinding.Property.PropertyType);
         }
         catch (Exception exception)
         {
             Result.Errors.Add(exception);
         }
     }
     base.VisitPropertyBinding(propertyBinding);
 }
Exemple #3
0
        public Expression <BindingUpdateDelegate> CompileToUpdateDelegate(ParsedExpressionBindingProperty binding, DataContextStack dataContext)
        {
            var valueParameter = Expression.Parameter(typeof(object), "value");
            var expr           = BindingCompiler.ReplaceParameters(binding.Expression, dataContext);

            // don't throw exception, it is annoying to debug.
            if (expr.NodeType != ExpressionType.Parameter &&
                (expr.NodeType != ExpressionType.MemberAccess || (!expr.CastTo <MemberExpression>().Member.As <PropertyInfo>()?.CanWrite ?? false)) &&
                expr.NodeType != ExpressionType.Index)
            {
                return(null);
            }

            var assignment = Expression.Assign(expr, Expression.Convert(valueParameter, expr.Type));

            return(Expression.Lambda <BindingUpdateDelegate>(assignment, BindingCompiler.ViewModelsParameter, BindingCompiler.CurrentControlParameter, valueParameter));
        }
Exemple #4
0
        public Expression <BindingUpdateDelegate> CompileToUpdateDelegate(ParsedExpressionBindingProperty binding, DataContextStack dataContext)
        {
            var valueParameter = Expression.Parameter(typeof(object), "value");
            var body           = BindingCompiler.ReplaceParameters(binding.Expression, dataContext);

            body = ExpressionHelper.UpdateMember(body, valueParameter);
            if (body == null)
            {
                return(null);
            }

            return(Expression.Lambda <BindingUpdateDelegate>(
                       body,
                       BindingCompiler.ViewModelsParameter,
                       BindingCompiler.CurrentControlParameter,
                       valueParameter));
        }
        public (Expression builder, ParameterExpression[] fields) CreateBuilder(DotvvmConfiguration configuration)
        {
            var dict       = new Dictionary <object, Expression>();
            var callStack  = new HashSet <object>();
            var locals     = new List <ParameterExpression>();
            var results    = new List <ParameterExpression>();
            var body       = new List <Expression>();
            var dedupCache = new Dictionary <Expression, ParameterExpression>(ExpressionComparer.Instance);

            //var presetObjects = new Dictionary<object, Expression>();
            MapObject(configuration, DotvvmConfigurationParameter, dict);

            Expression serializeObject(object obj, Type expectedType)
            {
                if (obj == null)
                {
                    return(Expression.Constant(null, expectedType));
                }
                if (dict.TryGetValue(obj, out var rrrr))
                {
                    return(rrrr);
                }
                if (!callStack.Add(obj))
                {
                    throw new NotSupportedException($"Reference cycles are not supported.");
                }
                var objType = obj.GetType();

                ParameterExpression ret(Expression e, bool thisobj = true)
                {
                    if (dedupCache.TryGetValue(e, out var p))
                    {
                        return(p);
                    }
                    p = Expression.Parameter(e.Type);
                    body.Add(Expression.Assign(p, e));
                    if (thisobj)
                    {
                        dict.Add(obj, p);
                    }
                    locals.Add(p);
                    dedupCache.Add(e, p);
                    return(p);
                }

                try
                {
                    if (KnownObjects.TryGetValue(obj, out var result))
                    {
                        return(result);
                    }
                    else if (objType.IsPrimitive || obj is string || obj is MemberInfo)
                    {
                        return(Expression.Constant(obj, objType.GetPublicBaseType()));
                    }
                    else if (obj is System.Collections.IEnumerable collection)
                    {
                        var        element = ReflectionUtils.GetEnumerableType(collection.GetType());
                        Expression expr    = collection.OfType <object>()
                                             .Select(e => serializeObject(e, element))
                                             .Apply(c => Expression.NewArrayInit(element, c));
                        if (!objType.IsArray)
                        {
                            var targetType = objType.Name == "ImmutableList`1" ? typeof(ImmutableList) :
                                             //objType.Name == "ImmutableDictionary" ? typeof(ImmutableDictionary) :
                                             typeof(ImmutableArray);
                            expr = expr.Apply(c => Expression.Call(null, targetType
                                                                   .GetMethods(BindingFlags.Static | BindingFlags.Public)
                                                                   .First(m => (m.Name == "Create" || m.Name == "To" + targetType.Name) && m.GetParameters().FirstOrDefault()?.ParameterType.IsArray == true)
                                                                   .MakeGenericMethod(new[] { element }),
                                                                   c
                                                                   ));
                        }
                        return(Expression.Convert(ret(expr), expectedType));
                    }
                    else if (obj is Expression expression)
                    {
                        return(ret(Expression.Quote(expression)));
                    }
                    else if (obj is Delegate deleg)
                    {
                        if (!translatedDelegates.TryGetValue(deleg, out var method))
                        {
                            throw new NotSupportedException("Could not serialize delegate");
                        }
                        var(sanitizedMethod, parameters) = UnallowedConstantRemover.ReplaceBadConstants(method);
                        return(ret(ExpressionUtils.Replace(Expression.Lambda(sanitizedMethod, parameters.Select(l => l.Item1)), parameters.Select(p => serializeObject(p.Item2, p.Item1.Type)).ToArray())));
                    }
                    else if (obj is IBinding binding)
                    {
                        var properties = BindingCompiler.GetMinimalCloneProperties(binding)
                                         .Select(p => serializeObject(p, p.GetType()))
                                         .Apply(p => Expression.NewArrayInit(typeof(object), p));

                        return(ret(Expression.New(
                                       binding.GetType().GetConstructor(new[] { typeof(BindingCompilationService), typeof(IEnumerable <object>) }),
                                       ret(BindingCompilationService, thisobj: false),
                                       properties
                                       )));
                    }
                    else
                    {
                        var map      = Map(objType.GetPublicBaseType());
                        var ctorArgs = map.CtorArguments.Select(p => serializeObject(Evaluate(p, obj), p.ReturnType)).ToArray();
                        var newObj   = ExpressionUtils.Replace(map.Ctor, ctorArgs);
                        if (!newObj.Type.IsValueType || map.Properties.Any())
                        {
                            newObj = ret(newObj);
                        }
                        foreach (var prop in map.Properties)
                        {
                            body.Add(ExpressionUtils.Replace(prop.Setter, newObj, serializeObject(Evaluate(prop.Getter, obj), prop.Getter.ReturnType)));
                        }
                        return(newObj);
                    }
                }
                finally
                {
                    callStack.Remove(obj);
                }
            }

            foreach (var req in requiredObjects)
            {
                var expr  = serializeObject(req.Key, req.GetType().GetPublicBaseType());
                var field = Expression.Parameter(req.Key.GetType().GetPublicBaseType(), req.Value);
                body.Add(Expression.Assign(field, expr));
                results.Add(field);
            }
            return(Expression.Block(locals, body), results.ToArray());
        }