/// <summary>
        /// Write new variable values and commit, evaluating assignment expressions using the given
        /// events per stream.
        /// <para />Populates an optional map of new values if a non-null map is passed.
        /// </summary>
        /// <param name="variableService">variable service</param>
        /// <param name="eventsPerStream">events per stream</param>
        /// <param name="valuesWritten">null or an empty map to populate with written values</param>
        /// <param name="exprEvaluatorContext">expression evaluation context</param>
        public void WriteVariables(VariableService variableService,
                                   EventBean[] eventsPerStream,
                                   IDictionary <String, Object> valuesWritten,
                                   ExprEvaluatorContext exprEvaluatorContext)
        {
            ISet <String> variablesBeansCopied = null;

            if (!_copyMethods.IsEmpty())
            {
                variablesBeansCopied = new HashSet <String>();
            }

            // We obtain a write lock global to the variable space
            // Since expressions can contain variables themselves, these need to be unchangeable for the duration
            // as there could be multiple statements that do "var1 = var1 + 1".
            using (variableService.ReadWriteLock.AcquireWriteLock())
            {
                try
                {
                    variableService.SetLocalVersion();

                    var count = 0;
                    foreach (var assignment in _assignments)
                    {
                        var variableMetaData = _metaData[count];
                        int agentInstanceId  = variableMetaData.ContextPartitionName == null ? EPStatementStartMethodConst.DEFAULT_AGENT_INSTANCE_ID : exprEvaluatorContext.AgentInstanceId;
                        var value            = assignment.Evaluator.Evaluate(
                            new EvaluateParams(eventsPerStream, true, exprEvaluatorContext));

                        if (_writers[count] != null)
                        {
                            var reader = variableService.GetReader(
                                variableMetaData.VariableName, exprEvaluatorContext.AgentInstanceId);
                            var current = (EventBean)reader.Value;
                            if (current == null)
                            {
                                value = null;
                            }
                            else
                            {
                                var writeDesc = _writers[count];
                                var copy      = variablesBeansCopied.Add(writeDesc.VariableName);
                                if (copy)
                                {
                                    var copied = _copyMethods.Get(writeDesc.Type).Copy(current);
                                    current = copied;
                                }
                                variableService.Write(variableMetaData.VariableNumber, agentInstanceId, current);
                                writeDesc.Writer.Write(value, current);
                            }
                        }
                        else if (variableMetaData.EventType != null)
                        {
                            var eventBean = _eventAdapterService.AdapterForType(value, variableMetaData.EventType);
                            variableService.Write(variableMetaData.VariableNumber, agentInstanceId, eventBean);
                        }
                        else
                        {
                            if ((value != null) && (_mustCoerce[count]))
                            {
                                value = CoercerFactory.CoerceBoxed(value, variableMetaData.VariableType);
                            }
                            variableService.Write(variableMetaData.VariableNumber, agentInstanceId, value);
                        }

                        count++;

                        if (valuesWritten != null)
                        {
                            valuesWritten.Put(assignment.VariableName, value);
                        }
                    }

                    variableService.Commit();
                }
                catch (Exception ex)
                {
                    Log.Error("Error evaluating on-set variable expressions: " + ex.Message, ex);
                    variableService.Rollback();
                }
            }
        }