public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { if (variableType == null) { throw new Exception("Variable type not yet set. Cannot create a VariableReference of unknown type"); } return(new[] { VariableReference.Create(variableType, (value as string) ?? ""), Binding.DoNothing }); // Send DoNothing as the binding that was used to get the type so that we do not set it }
/// <summary> /// Compiles the entries in the given Program into delegates. /// Returns the delegates themselves and the delegate signatures (excluding the context parameter). /// </summary> private FunctionStore CompileEntryDelegates(VisualProgram program) { var progEntryNodes = program.Nodes.OfType <VisualEntry>().ToDictionary(ve => ve.VisualEntryId, ve => ve); return(program.Environment.EntryDefinitions.ToDictionary( entry => entry.Key, entry => { // If the program does not contain this entry node OR it exists but is not connected to any statements, then return no delegate if (!progEntryNodes.TryGetValue(entry.Value.Id, out var startNode) || !startNode.FirstStatement.HasValue) { return null; } // Create a parameter for each expected/defined parameter var parameters = entry.Value.Parameters.Map(Expression.Parameter); // Compile and return the lambda return Expression.Lambda( Expression.Block( // Before doing the main body of the entry function, make expressions to copy the incoming parameters to variables startNode.ParameterMap .Where(mapping => !string.IsNullOrWhiteSpace(mapping.Value)) // Exclude any that don't actually map to anything .Select(p => VariableAccessorFactory.CreateSetterExpression( program, VariableReference.Create(entry.Value.Parameters[p.Key], p.Value), parameters[p.Key] ) ).Concat( // Then do the actual main body NodeUtils.FlattenExpressions(program, startNode.FirstStatement) ) ), // All lambdas will get a context parameter // We also pass the defined parameters to the lambda so it knows what types to expect and what signature to have. // This needs to happen regardless or not of whether the parameters are actually used by the entry function as this determines the delegate's signature. new[] { program.Variables.compiledInstanceParameter }.Concat(parameters) ).Compile(); }, StringComparer.OrdinalIgnoreCase )); }