示例#1
0
        /// <summary>
        /// 通过脚本动态确定用户列表
        /// </summary>
        /// <param name="script"></param>
        /// <param name="flowDynamicUserName"></param>
        /// <param name="flowInstance"></param>
        /// <returns></returns>
        private static List <UserDTO> ResolveFlowDynamicUser(
            string script, string flowDynamicUserName, FlowInstance flowInstance)
        {
            #region 初始化执行环境
            var _session = new DictionaryContext();
            _session.globals.Add("flowInstance", flowInstance);
            var _references = new Assembly[] { typeof(DictionaryContext).Assembly,
                                               typeof(System.Runtime.CompilerServices.DynamicAttribute).Assembly,
                                               typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo).Assembly,
                                               typeof(ExpandoObject).Assembly,
                                               typeof(JsonConvert).Assembly,
                                               typeof(ExpandoObjectConverter).Assembly,
                                               typeof(Paticipant).Assembly,
                                               typeof(UserDTO).Assembly,
                                               typeof(FlowInstance).Assembly,
                                               typeof(List <>).Assembly };
            var _imports = new string[] { typeof(DictionaryContext).Namespace,
                                          typeof(System.Runtime.CompilerServices.DynamicAttribute).Namespace,
                                          typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo).Namespace,
                                          typeof(ExpandoObject).Namespace,
                                          typeof(JsonConvert).Namespace,
                                          typeof(ExpandoObjectConverter).Namespace,
                                          typeof(Paticipant).Namespace,
                                          typeof(UserDTO).Namespace,
                                          typeof(FlowInstance).Namespace,
                                          typeof(List <>).Namespace };
            var _options = ScriptOptions.Default
                           .AddReferences(_references)
                           .AddImports(_imports);
            #endregion

            #region 执行
            try
            {
                var result = CSharpScript.RunAsync(script,
                                                   globals: _session, options: _options).Result.ReturnValue;
                return((List <UserDTO>)result);
            }
            catch (Exception ex) // 默默记录到日志并继续执行
            {
                var _ex = ex;
                logger.Error(ex.Message,
                             "运行脚本解析流程动态用户出错, 流程实例id:{0}; 流程动态用户名:{1}; ",
                             flowInstance.flowInstanceId, flowDynamicUserName);
                return(null);
            }
            #endregion
        }
示例#2
0
        ExecuteAutoRulesAsync(List <ConditionRule> autoRules,
                              string bizDataPayloadJson, string optionalFlowActionDataJson,
                              FlowInstance flowInstance)
        {
            #region 各类执行前合法性检查
            if (autoRules == null || autoRules.Count() == 0)
            {
                logger.Error("自动规则脚本集为空,流程实例无法继续执行: 流程实例id:{0}; 活动名:{1};",
                             flowInstance.flowInstanceId, flowInstance.currentActivityName);
            }
            #endregion

            #region 初始化各类辅助环境参数
            var _ttl        = 5;
            var _session    = new DictionaryContext();
            var _references = new Assembly[] { typeof(DictionaryContext).Assembly,
                                               typeof(System.Runtime.CompilerServices.DynamicAttribute).Assembly,
                                               typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo).Assembly,
                                               typeof(System.Dynamic.ExpandoObject).Assembly,
                                               typeof(JsonConvert).Assembly,
                                               typeof(ExpandoObjectConverter).Assembly,
                                               typeof(Paticipant).Assembly,
                                               typeof(UserDTO).Assembly,
                                               typeof(Logger).Assembly, };
            var _imports = new string[] { typeof(DictionaryContext).Namespace,
                                          typeof(System.Runtime.CompilerServices.DynamicAttribute).Namespace,
                                          typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo).Namespace,
                                          typeof(System.Dynamic.ExpandoObject).Namespace,
                                          typeof(JsonConvert).Namespace,
                                          typeof(ExpandoObjectConverter).Namespace,
                                          typeof(Paticipant).Namespace,
                                          typeof(UserDTO).Namespace, };
            var _options = ScriptOptions.Default
                           .AddReferences(_references)
                           .AddImports(_imports);

            //脚本环境可用的两个动态全局变量
            #region 一些尝试代码
            //dynamic biz = parseJsonToDynamicObject(bizDataPayloadJson);
            //_session.globals.Add("BizData",
            //  JsonConvert.DeserializeObject<ExpandoObject>(
            //    bizDataPayloadJson, new ExpandoObjectConverter()));
            //_session.globals.Add("FlowActionData",
            //  JsonConvert.DeserializeObject<ExpandoObject>(
            //    optionalFlowActionDataJson, new ExpandoObjectConverter()));
            //string buildBizData = @"dynamic BizData = JsonConvert.DeserializeObject<ExpandoObject>((string)globals[""BizDataJson""], new ExpandoObjectConverter());";
            #endregion
            _session.globals.Add("BizDataJson", bizDataPayloadJson);
            _session.globals.Add("FlowActionDataJson", optionalFlowActionDataJson);

            string buildBizData        = parseJsonToDynamicCode(bizDataPayloadJson, "BizData");
            string buildFlowActionData = parseJsonToDynamicCode(optionalFlowActionDataJson, "FlowActionData");

            ScriptState <object> state = null;
            #endregion

            #region 反复运行自动规则脚本集数次,直到确定无法返回(借鉴了Angular 1的做法)
            Dictionary <string, string> ruleCodeDict =
                new Dictionary <string, string>(autoRules.Count());
            while (_ttl > 0)
            {
                foreach (var rule in autoRules)
                {
                    var codeDecoded = "";
                    try
                    {
                        #region 因为自动规则脚本进行了base64编码,为保证性能对解码的脚本进行缓存
                        if (ruleCodeDict.ContainsKey(rule.guid))
                        {
                            codeDecoded = ruleCodeDict[rule.guid];
                        }
                        else
                        {
                            codeDecoded = Encoding.UTF8.GetString(Convert.FromBase64String(rule.code));
                            ruleCodeDict.Add(rule.guid, codeDecoded);
                        }
                        #endregion

                        #region 执行脚本
                        state = state == null ?
                                await CSharpScript.RunAsync( // 如果是首次运行,需要在脚本前面加入生成BizData对象的动态代码
                            buildBizData + buildFlowActionData + codeDecoded,
                            globals : _session, options : _options)
                  :
                                await state.ContinueWithAsync(
                            codeDecoded, options : _options);

                        #endregion
                    }
                    catch (Exception ex) // 默默记录到日志并继续执行
                    {
                        var _ex = ex;
                        logger.Error(ex.Message,
                                     "运行自动规则脚本出错, 流程实例id:{0}; 活动名:{1}; 规则名:{2}; 规则代码(已解码): {3};规则代码(未解码): {4};",
                                     flowInstance.flowInstanceId, flowInstance.currentActivityName,
                                     rule.name, codeDecoded, rule.code);
                    }
                    if (state != null && state.ReturnValue != null &&
                        state.ReturnValue is bool && (bool)state.ReturnValue) // 如果返回值为true
                    {
                        var _paticipants = rule.paticipants;
                        //如果在自动规则脚本里自行创建了类型为List<Paticipant>的名为Paticipants的对象,
                        //则覆盖规则定义里默认的paticipants值
                        if (_session.globals.ContainsKey("Paticipants") &&
                            _session.globals["Paticipants"] is List <Paticipant> )
                        {
                            _paticipants = (List <Paticipant>)_session.globals["Paticipants"];
                        }
                        logger.Trace("运行自动规则脚本获得生效的规则, 流程实例id:{0}; 活动名:{1}; 规则名:{2};",
                                     flowInstance.flowInstanceId, flowInstance.currentActivityName, rule.name);
                        return(new Tuple <string, List <Paticipant> >(
                                   rule.connectionGuid, _paticipants));
                    }
                }
                _ttl--;
            }
            #endregion

            #region 确保返回一个规则结果, 如果上面没有获得生效的规则, 取首个默认退出规则(如果有)或最后一个规则
            var firstDefault = autoRules.First(rule => rule.isDefault);
            if (firstDefault != null)
            {
                logger.Warn(@"运行自动规则脚本集未能获得生效的规则,取首个默认退出规则, \
          流程实例id:{0}; 活动名:{1}; 规则名:{2};",
                            flowInstance.flowInstanceId, flowInstance.currentActivityName, firstDefault.name);
                return(new Tuple <string, List <Paticipant> >(
                           firstDefault.connectionGuid, firstDefault.paticipants));
            }
            else
            {
                var _lastIdx = autoRules.Count() - 1;
                logger.Warn(@"运行自动规则脚本集未能获得生效的规则,取最后一个规则, \
          流程实例id:{0}; 活动名:{1}; 规则名:{2};",
                            flowInstance.flowInstanceId, flowInstance.currentActivityName, autoRules[_lastIdx].name);
                return(new Tuple <string, List <Paticipant> >(
                           autoRules[_lastIdx].connectionGuid,
                           autoRules[_lastIdx].paticipants));
            }
            #endregion
        }