public static string GetArgsScript(MethodCallExpression expression, DataContextStack dataContext) { var target = expression.Object == null ? null : JavascriptTranslator.CompileToJavascript(expression.Object, dataContext); var arguments = (target == null ? new string[0] : new[] { target }) .Concat(expression.Arguments.Select(a => JavascriptTranslator.CompileToJavascript(a, dataContext))); return "[" + String.Join(", ", arguments) + "]"; }
public static string CompileToJavascript(Expression binding, DataContextStack dataContext) { var translator = new JavascriptTranslator(); translator.DataContexts = dataContext; var script = translator.Translate(binding).Trim(); if (binding.NodeType == ExpressionType.MemberAccess && script.EndsWith("()", StringComparison.Ordinal)) script = script.Remove(script.Length - 2); return script; }
public virtual Expression<CompiledBindingExpression.BindingDelegate> CompileToDelegate(Expression binding, DataContextStack dataContext, Type expectedType) { var viewModelsParameter = Expression.Parameter(typeof(object[]), "vm"); var controlRootParameter = Expression.Parameter(typeof(DotvvmBindableObject), "controlRoot"); var expr = ExpressionUtils.Replace(ConvertExpressionToType(binding, expectedType), BindingCompiler.GetParameters(dataContext, viewModelsParameter, Expression.Convert(controlRootParameter, dataContext.RootControlType))); expr = ExpressionUtils.ConvertToObject(expr); return Expression.Lambda<CompiledBindingExpression.BindingDelegate>(expr, viewModelsParameter, controlRootParameter); }
public virtual Expression<CompiledBindingExpression.BindingUpdateDelegate> CompileToUpdateDelegate(Expression binding, DataContextStack dataContext) { var viewModelsParameter = Expression.Parameter(typeof(object[]), "vm"); var controlRootParameter = Expression.Parameter(typeof(DotvvmBindableObject), "controlRoot"); var valueParameter = Expression.Parameter(typeof(object), "value"); var expr = ExpressionUtils.Replace(binding, BindingCompiler.GetParameters(dataContext, viewModelsParameter, Expression.Convert(controlRootParameter, dataContext.RootControlType))); var assignment = Expression.Assign(expr, Expression.Convert(valueParameter, expr.Type)); return Expression.Lambda<CompiledBindingExpression.BindingUpdateDelegate>(assignment, viewModelsParameter, controlRootParameter, valueParameter); }
protected override IDataContextStack CreateDataContextTypeStack(ITypeDescriptor viewModelType, ITypeDescriptor wrapperType = null, IDataContextStack parentDataContextStack = null) { var dataContextTypeStack = new DataContextStack(ResolvedTypeDescriptor.ToSystemType(viewModelType), parentDataContextStack as DataContextStack); if (wrapperType != null) { dataContextTypeStack.RootControlType = ResolvedTypeDescriptor.ToSystemType(wrapperType); } return dataContextTypeStack; }
public object CompileBinding(string expression, params Type[] contexts) { var context = new DataContextStack(contexts.FirstOrDefault() ?? typeof(object)); context.RootControlType = typeof(DotvvmControl); for (int i = 1; i < contexts.Length; i++) { context = new DataContextStack(contexts[i], context); } var parser = new BindingExpressionBuilder(); var expressionTree = parser.Parse(expression, context, BindingParserOptions.Create<ValueBindingExpression>()); return JavascriptTranslator.CompileToJavascript(expressionTree, context); }
protected virtual string CompileMethodCall(MethodCallExpression methodExpression, DataContextStack dataContext, string callbackFunction = null) { if (!Attribute.IsDefined(methodExpression.Method, typeof(AllowStaticCommandAttribute))) throw new Exception($"Method '{methodExpression.Method.DeclaringType.Name}.{methodExpression.Method.Name}' used in static command has to be marked with [AllowStaticCommand] attribute."); if (callbackFunction == null) callbackFunction = "null"; if (methodExpression == null) { throw new NotSupportedException("Static command binding must be a method call!"); } var argsScript = GetArgsScript(methodExpression, dataContext); return $"dotvvm.staticCommandPostback(i_pageArea, sender, '{GetMethodName(methodExpression)}', { argsScript }, {callbackFunction})"; }
public override void VisitControl(ResolvedControl control) { var position = control.DothtmlNode.StartPosition; var returnType = CurrentType; if (CurrentType != control.DataContextTypeStack) { CurrentType = control.DataContextTypeStack; Result.Controls.Add(position, new ControlCompilationInfo { DataContext = control.DataContextTypeStack.DataContextType.ToString() }); } base.VisitControl(control); CurrentType = returnType; }
public static TypeRegistry AddTypeSymbols(TypeRegistry reg, DataContextStack dataContext) { var namespaces = dataContext.Enumerable().Select(t => t.Namespace).Except(new[] { "System" }).Distinct(); return reg.AddSymbols(new[] { // ViewModel is alias for current viewmodel type new KeyValuePair<string, Expression>("ViewModel", TypeRegistry.CreateStatic(dataContext.DataContextType)), // RootViewModel alias for root view model type new KeyValuePair<string, Expression>("RootViewModel", TypeRegistry.CreateStatic(dataContext.Enumerable().Last())), }) // alias for any viewModel in hierarchy : .AddSymbols(dataContext.Enumerable() .Select((t, i) => new KeyValuePair<string, Expression>($"Parent{i}ViewModel", TypeRegistry.CreateStatic(t)))) // import all viewModel namespaces .AddSymbols(namespaces.Select(ns => (Func<string, Expression>)(typeName => TypeRegistry.CreateStatic(ReflectionUtils.FindType(ns + "." + typeName))))); }
public Expression Parse(string expression, DataContextStack dataContexts, BindingParserOptions options) { try { var tokenizer = new BindingTokenizer(); tokenizer.Tokenize(new StringReader(expression)); var parser = new BindingParser(); parser.Tokens = tokenizer.Tokens; var node = parser.ReadExpression(); if (!parser.OnEnd()) { throw new BindingCompilationException( $"Unexpected token '{expression.Substring(0, parser.Peek().StartPosition)} ---->{parser.Peek().Text}<---- {expression.Substring(parser.Peek().StartPosition + parser.Peek().Length)}'", null, new TokenBase[] { parser.Peek() }); } foreach (var n in node.EnumerateNodes()) { if (n.HasNodeErrors) throw new BindingCompilationException(string.Join(", ", n.NodeErrors), n); } var symbols = InitSymbols(dataContexts); symbols = options.AddTypes(symbols); var visitor = new ExpressionBuildingVisitor(symbols); visitor.Scope = symbols.Resolve(options.ScopeParameter); return visitor.Visit(node); } catch (Exception ex) { ex.ForInnerExceptions<BindingCompilationException>(bce => { if (bce.Expression == null) bce.Expression = expression; }); throw; } }
public static IEnumerable<ParameterExpression> GetParameters(DataContextStack dataContext) { if (dataContext.RootControlType != null) { yield return Expression.Parameter(dataContext.RootControlType, "_control"); } yield return Expression.Parameter(dataContext.DataContextType, "_this"); yield return Expression.Parameter(typeof(BindingPageInfo), "_page"); var index = 1; while (dataContext.Parent != null) { dataContext = dataContext.Parent; if (index == 1) { yield return Expression.Parameter(dataContext.DataContextType, "_parent"); } else { yield return Expression.Parameter(dataContext.DataContextType, "_parent" + index); } index++; } yield return Expression.Parameter(dataContext.DataContextType, "_root"); }
/// <summary> /// Emits value or binding and returns /// </summary> protected ExpressionSyntax ProcessBindingOrValue(object obj, DataContextStack dataContext) { var binding = obj as ResolvedBinding; if (binding != null) return ProcessBinding(binding, typeof(object)); else return emitter.EmitValue(obj); }
protected void ProcessHtmlAttributes(string controlName, IDictionary<string, object> attributes, DataContextStack dataContext) { foreach (var attr in attributes) { var value = ProcessBindingOrValue(attr.Value, dataContext); emitter.EmitAddHtmlAttribute(controlName, attr.Key, value); } }
public override void VisitView(ResolvedTreeRoot view) { CurrentType = view.DataContextTypeStack; base.VisitView(view); }
public DataContextStack(Type type, DataContextStack parent = null) { Parent = parent; DataContextType = type; RootControlType = parent?.RootControlType; }
public static TypeRegistry InitSymbols(DataContextStack dataContext) { return AddTypeSymbols(TypeRegistry.Default.AddSymbols(GetParameters(dataContext).Select(d => new KeyValuePair<string, Expression>(d.Name, d))), dataContext); }