Example #1
0
 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
                       ));
        }