前一阵子学习了一下工作流,现在写个总结记录一下这个过程。要弄工作流,首先就要有个界面来画图,做web的,没办法,只能选择javascript和silverlight,找来找去,最后用了Shareidea的和Workflow11的界面,在此对他们表示感谢,界面是在Shareidea上面进行的修改,把Workflow11的很多东西也揉进来了,最后合成的一个杂交体。但是最后因为要玩hadoop,要清理磁盘空间,把工程给误删了,直到现在才发现。。我3个月的业余时间完成的代码全部被干掉了,已经无法挽回了,只能做一下追忆罢了,现在把残存的一些代码给发上来,算是纪念一下。

 /// <summary>
         /// 解析工作流
         /// </summary>
         /// <param name="xml"></param>
         /// <returns></returns>
         private string AnalyzerWorkFlow(string xml)
         {
             #region 读取xml信息,生成linq to xml 信息

             string xaml = string.Empty;
             //把字符串解析成XElement
             Byte[] b = System.Text.UTF8Encoding.UTF8.GetBytes(xml);
             XElement element = XElement.Load(System.Xml.XmlReader.Create(new MemoryStream(b)));

             #endregion

             #region 保存模板

             //模板信息
             var template = new Template();
             template.Name = element.Attribute(XName.Get("Name")).Value;
             template.Guid = Guid.Parse(element.Attribute(XName.Get("UniqueID")).Value);
             template.Version = element.Attribute(XName.Get("Version")).Value;
             template.Templates = xml;
             template.UpdateTime = DateTime.Now;

             #endregion

             #region 初始化变量

             //获取所有的activity和rule
             var nodes = from item in element.Descendants("Activity") select item;
             var rules = from item in element.Descendants("Rule") select item;
             //建立flowchart,从第一个节点开始遍历整个图
             Flowchart flowchart = new Flowchart()
             {
                 DisplayName = template.Name
             };
             IActivity activity;
             FlowNode preStep = new FlowStep();
             FlowNode nextStep;
             FlowSwitch<string> flowSwitch;
             XElement xele;
             IEnumerable<XElement> linkedRules;
             string uniqueId = string.Empty;
             string activityId = string.Empty;
             //实例化开始节点
             var firstNode = nodes.First((node) => node.Attribute(XName.Get("Type")).Value == "INITIAL");
             var startActivity = new StartActivity(firstNode.Attribute(XName.Get("UniqueID")).Value);
             startActivity.DisplayName = firstNode.Attribute(XName.Get("ActivityName")).Value;
             ((FlowStep)preStep).Action = startActivity;
             flowchart.Nodes.Add(preStep);
             flowchart.StartNode = preStep;
             //设置一个栈,把东西put进去;设置一个字典,把创建过的活动id,以及位置记录进去
             var stack = new Stack<IActivity>();
             var dic = new Dictionary<string, int>();
             stack.Push(startActivity);
             dic.Add(startActivity.ActivityId, flowchart.Nodes.Count - );

             #endregion

             #region 遍历生成flowchart图形

             )
             {
                 activity = stack.Pop();
                 activityId = activity.ActivityId;
                 linkedRules = from rule in rules
                               where rule.Attribute(XName.Get("BeginActivityUniqueID")).Value == activityId
                               select rule;
                 //节点被清空之后,重新定位
                 if (preStep == null)
                 {
                     preStep = flowchart.Nodes[dic[activityId]];
                 }
                 //后续活动有多个
                 )
                 {
                     //条件自动判断路径活动
                     if (activity is ConditionActivity)
                     {
                         #region 判断节点,根据用户事先预置的条件自动判断选择下一步节点

                         string trueActivityId = ((ConditionActivity)activity).Property.ActivityForTrue;
                         string falseActivityId = ((ConditionActivity)activity).Property.ActivityForFalse;

                         //把false写在前面是因为栈是倒序的,遍历节点按照倒序的方式来遍历了,但是在生成xaml的时候,
                         //生成出来的xaml的条件中的true节点的后续节点在后面呢,还没建立,所以无法引用到后续的节点
                         //只有前面的节点先建立了,后面的节点才能使用前面的节点的引用
                         if (!dic.ContainsKey(falseActivityId))
                         {
                             xele = nodes.First((node) =>
                                     node.Attribute(XName.Get("UniqueID")).Value == falseActivityId);
                             activity = GetActivityByType(xele);
                             nextStep = CreateFlowNodeByType(activity);
                             flowchart.Nodes.Add(nextStep);
                             dic.Add(falseActivityId, flowchart.Nodes.Count - );
                             ((FlowDecision)preStep).False = nextStep;
                             stack.Push(activity);
                         }
                         else
                         {
                             ((FlowDecision)preStep).False = flowchart.Nodes[(dic[falseActivityId])];
                         }

                         if (!dic.ContainsKey(trueActivityId))
                         {
                             xele = nodes.First((node) =>
                                     node.Attribute(XName.Get("UniqueID")).Value == trueActivityId);
                             activity = GetActivityByType(xele);
                             nextStep = CreateFlowNodeByType(activity);
                             flowchart.Nodes.Add(nextStep);
                             dic.Add(trueActivityId, flowchart.Nodes.Count - );
                             ((FlowDecision)preStep).True = nextStep;
                             preStep = nextStep;
                             stack.Push(activity);
                         }
                         else
                         {
                             ((FlowDecision)preStep).True = flowchart.Nodes[(dic[trueActivityId])];
                         }

                         #endregion

                     }
                     //用户选择路径活动
                     else if (activity is ActiveActivity)
                     {
                         //后续活动类型为串行
                         )
                         {
                             #region 串行活动,处理人选择下一步操作

                             flowSwitch = new FlowSwitch<string>();
                             flowSwitch.Expression = new VisualBasicValue<string>() { ExpressionText = "NextWay" };
                             flowSwitch.Default = flowchart.StartNode;
                             foreach (XElement linkedRule in linkedRules)
                             {
                                 uniqueId = linkedRule.Attribute(XName.Get("EndActivityUniqueID")).Value;
                                 if (!dic.ContainsKey(uniqueId))
                                 {
                                     xele = nodes.First((node) =>
                                         node.Attribute(XName.Get("UniqueID")).Value == uniqueId);
                                     activity = GetActivityByType(xele);
                                     nextStep = CreateFlowNodeByType(activity);
                                     flowchart.Nodes.Add(nextStep);
                                     dic.Add(activity.ActivityId, flowchart.Nodes.Count() - );
                                     flowSwitch.Cases.Add(uniqueId.ToLower(), nextStep);
                                     preStep = nextStep;
                                     stack.Push(activity);
                                 }
                                 else
                                 {
                                     flowSwitch.Cases.Add(uniqueId.ToLower(), flowchart.Nodes[(dic[uniqueId])]);
                                 }
                             }
                             flowchart.Nodes.Add(flowSwitch);
                             //通过activityId找到节点在flowchart中的位置,然后设置它的next节点
                             ((FlowStep)flowchart.Nodes[dic[activityId]]).Next =
                                 flowchart.Nodes[flowchart.Nodes.Count - ];

                             #endregion

                         }
                         //后续活动类型为并行活动
                         else
                         {
                             #region 并行活动

                             var parallel = new Parallel();
                             parallel.CompletionCondition = false;
                             Switch<string> witch;
                             Sequence seq;
                             ;
                             //取得汇合节点的id
                             var joinPointId = GetJoinPointId(rules, activityId);
                             foreach (XElement linkedRule in linkedRules)
                             {
                                 uniqueId = linkedRule.Attribute(XName.Get("EndActivityUniqueID")).Value;
                                 //如果连线直接连着
                                 if (uniqueId == joinPointId) continue;
                                 xele = nodes.First((node) =>
                                     node.Attribute(XName.Get("UniqueID")).Value == uniqueId);
                                 activity = GetActivityByType(xele);
                                 currentCount = stack.Count;
                                 seq = new Sequence();
                                 seq.Activities.Add((Activity)activity);
                                 stack.Push(activity);
                                 while (stack.Count > currentCount)
                                 {
                                     activity = stack.Pop();
                                     uniqueId = activity.ActivityId;
                                     var seqRules = from rule in rules
                                                    where
                                                        rule.Attribute(XName.Get("BeginActivityUniqueID")).Value ==
                                                        uniqueId
                                                    select rule;
                                     )
                                     {
                                         witch = new Switch<string>();
                                         witch.Expression = new VisualBasicValue<string>()
                                             {
                                                 ExpressionText = "NextWay"
                                             };
                                         foreach (XElement seqRule in seqRules)
                                         {
                                             var caseId = seqRule.Attribute("EndActivityUniqueID").Value;
                                             if (caseId != joinPointId)
                                             {
                                                 xele = nodes.First((node) =>
                                                 node.Attribute(XName.Get("UniqueID")).Value == caseId);
                                                 activity = GetActivityByType(xele);
                                                 witch.Cases.Add(caseId.ToLower(), (Activity)activity);
                                                 stack.Push(activity);
                                             }
                                         }
                                         seq.Activities.Add(witch);
                                     }
                                     )
                                     {
                                         uniqueId = seqRules.First().Attribute("EndActivityUniqueID").Value;
                                         if (uniqueId != joinPointId)
                                         {
                                             xele = nodes.First((node) =>
                                                  node.Attribute(XName.Get("UniqueID")).Value == uniqueId);
                                             activity = GetActivityByType(xele);
                                             seq.Activities.Add((Activity)activity);
                                             stack.Push(activity);
                                         }
                                     }
                                 }
                                 parallel.Branches.Add(seq);
                             }
                             //并行节点作为flowchart中的一个节点来处理
                             nextStep = new FlowStep();
                             ((FlowStep)nextStep).Action = parallel;
                             ((FlowStep)preStep).Next = nextStep;
                             flowchart.Nodes.Add(nextStep);
                             preStep = nextStep;
                             //处理完并行结构之后,添加汇合节点
                             xele = nodes.First((node) =>
                                     node.Attribute(XName.Get("UniqueID")).Value == uniqueId);
                             activity = GetActivityByType(xele);
                             nextStep = CreateFlowNodeByType(activity);
                             flowchart.Nodes.Add(nextStep);
                             dic.Add(activity.ActivityId, flowchart.Nodes.Count() - );
                             ((FlowStep)preStep).Next = nextStep;
                             preStep = nextStep;
                             stack.Push(activity);

                             #endregion
                         }
                     }
                 }
                 //后续活动只有一个
                 )
                 {
                     #region 后续只有一个活动节点

                     uniqueId = linkedRules.First().Attribute("EndActivityUniqueID").Value;

                     if (!dic.ContainsKey(uniqueId))
                     {
                         xele = nodes.First((node) => node.Attribute(XName.Get("UniqueID")).Value == uniqueId);
                         activity = GetActivityByType(xele);
                         nextStep = CreateFlowNodeByType(activity);
                         flowchart.Nodes.Add(nextStep);
                         dic.Add(activity.ActivityId, flowchart.Nodes.Count() - );
                         ((FlowStep)preStep).Next = nextStep;
                         preStep = nextStep;
                         stack.Push(activity);
                     }
                     else
                     {
                         //活动已存在,通过dic字典中记录的位置,将“前节点”的Next指针指向它
                         ((FlowStep)flowchart.Nodes[dic[activityId]]).Next =
                             flowchart.Nodes[dic[uniqueId]];
                         //((FlowStep)preStep).Next = flowchart.Nodes.ElementAt(dic[uniqueId]);
                     }

                     #endregion
                 }
                 //没有后续节点
                 else
                 {
                     //如果没有后续节点,则把“前节点”清空,然后重新定位前节点
                     preStep = null;
                 }

             }

             #endregion

             #region 将图形转成xaml格式的文件,并且保存

             try
             {

                 xaml = GetXmlFromActiviyBuilder(flowchart);
                 //xaml = XamlServices.Save(flowchart);
                 template.XamlTemplate = xaml;
                 using (var scope = new System.Transactions.TransactionScope())
                 {
                     TemplateService.AddTemplate(template);
                     CreateRoad(rules, template.Guid);
                     scope.Complete();
                 }

             }
             catch (Exception ex)
             {
                 xaml = ex.Message;
             }

             #endregion

             return xaml;
         }

         #region 辅助函数

         /// <summary>
         /// 通过ActivityBuilder给添加一个传入参数,否则无法传值。
         /// </summary>
         /// <param name="flowchart"></param>
         /// <returns></returns>
         private string GetXmlFromActiviyBuilder(Flowchart flowchart)
         {
             ActivityBuilder ab = new ActivityBuilder();
             ab.Implementation = flowchart;
             ab.Properties.Add(new DynamicActivityProperty()
             {
                 Name = "Entity",
                 Type = typeof(InOutArgument<object>)
             });
             ab.Properties.Add(new DynamicActivityProperty()
             {
                 Name = "NextWay",
                 Type = typeof(InOutArgument<string>)
             });
             StringBuilder stringBuilder = new StringBuilder();
             StringWriter stringWriter = new StringWriter(stringBuilder);
             XamlSchemaContext xamlSchemaContext = new XamlSchemaContext();
             XamlXmlWriter xamlXmlWriter = new XamlXmlWriter(stringWriter, xamlSchemaContext);
             XamlWriter xamlWriter = ActivityXamlServices.CreateBuilderWriter(xamlXmlWriter);
             XamlServices.Save(xamlWriter, ab);
             return stringBuilder.ToString();
         }

         /// <summary>
         /// 创建路径线路图,用于用户打开单据时候,生成操作按钮
         /// </summary>
         /// <param name="rules"></param>
         /// <param name="templateId"></param>
         private void CreateRoad(IEnumerable<XElement> rules, Guid templateId)
         {
             var roadList = new List<object>();
             TemplateRoads road = null;
             foreach (var rule in rules)
             {
                 road = new TemplateRoads();
                 road.Id = Guid.NewGuid();
                 road.Source = rule.Attribute(XName.Get("BeginActivityUniqueID")).Value;
                 road.Target = rule.Attribute(XName.Get("EndActivityUniqueID")).Value;
                 road.Name = rule.Attribute(XName.Get("RuleName")).Value;
                 road.TemplateId = templateId;
                 //这个是控制他们的顺序的
                 road.Zindex = Convert.ToInt32(rule.Attribute(XName.Get("ZIndex")).Value);
                 roadList.Add(road);
             }
             DBHelper.WriteDataTableToDb(Common.FillDataTable(roadList));
         }

         /// <summary>
         /// 创建路径线路图,用于用户打开单据时候,生成操作按钮
         /// </summary>
         /// <param name="activitys"></param>
         /// <param name="templateId"></param>
         private void CreateActivitys(IEnumerable<XElement> activitys, Guid templateId)
         {
             var roadList = new List<object>();
             TemplateRoads road;
             foreach (var activity in activitys)
             {
                 road = new TemplateRoads();
                 road.Id = Guid.NewGuid();
                 road.Source = activity.Attribute(XName.Get("BeginActivityUniqueID")).Value;
                 road.Target = activity.Attribute(XName.Get("EndActivityUniqueID")).Value;
                 road.Name = activity.Attribute(XName.Get("RuleName")).Value;
                 road.TemplateId = templateId;
                 //这个是控制他们的顺序的
                 road.Zindex = Convert.ToInt32(activity.Attribute(XName.Get("ZIndex")).Value);
                 roadList.Add(road);
             }
             DBHelper.WriteDataTableToDb(Common.FillDataTable(roadList));
         }

         /// <summary>
         /// 通过开始分叉节点的id,计算流程汇合的节点的id
         /// </summary>
         /// <param name="rules">所有的线路</param>
         /// <param name="startNodeId">开始节点的id</param>
         /// <returns></returns>
         private string GetJoinPointId(IEnumerable<XElement> rules, string startNodeId)
         {
             var linkedRules = from rule in rules
                               where rule.Attribute(XName.Get("BeginActivityUniqueID")).Value == startNodeId
                               select rule;

             )
             {
                 var list = new List<IEnumerable<XElement>>();
                 var uniqueId = string.Empty;
                 ; i < linkedRules.Count(); i++)
                 {
                     uniqueId = linkedRules.ElementAt(i).Attribute(XName.Get("EndActivityUniqueID")).Value;
                     list.Add(GetAfterRules(rules, uniqueId).ToList());
                 }
                 //计算交集
                 IEnumerable<XElement> result = null;
                 foreach (IEnumerable<XElement> item in list)
                 {
                     if (result == null)
                     {
                         result = item;
                     }
                     else
                     {
                         result = result.Intersect(item);
                     }
                 }
                 )
                 {
                     return result.First().Attribute(XName.Get("BeginActivityUniqueID")).Value;
                 }

             }

             return null;

         }

         /// <summary>
         /// 递归查找某个节点的后续连线
         /// </summary>
         /// <param name="rules">所有的线路</param>
         /// <param name="startNodeId">开始节点</param>
         /// <returns></returns>
         private IEnumerable<XElement> GetAfterRules(IEnumerable<XElement> rules, string startNodeId)
         {
             var linkedRules = from rule in rules
                               where rule.Attribute(XName.Get("BeginActivityUniqueID")).Value == startNodeId
                               select rule;

             return linkedRules.ToList().Concat(linkedRules.ToList().SelectMany(
                 t => GetAfterRules(rules, t.Attribute(XName.Get("EndActivityUniqueID")).Value)));
         }

         /// <summary>
         /// 根据activity的类型,返回相应的FlowNode节点类型
         /// </summary>
         /// <param name="activity"></param>
         /// <returns></returns>
         private FlowNode CreateFlowNodeByType(IActivity activity)
         {
             if (activity is ConditionActivity)
             {
                 return new FlowDecision() { Condition = activity as ConditionActivity };
             }
             else
             {
                 return new FlowStep() { Action = (Activity)activity };
             }
         }

         /// <summary>
         /// 通过类型来创建活动
         /// </summary>
         /// <param name="element">节点元素</param>
         /// <returns>返回对应的活动</returns>
         private IActivity GetActivityByType(XElement element)
         {
             var uniqueId = element.Attribute(XName.Get("UniqueID")).Value;
             var type = element.Attribute(XName.Get("Type")).Value;
             //取得属性节点
             var property = element.FirstNode.NextNode as XElement;
             dynamic propertyObj = null;

             switch (type)
             {
                 case "INITIAL":
                     return new StartActivity(uniqueId);
                 case "COMPLETION":
                     return new EndActivity(uniqueId);
                 case "INTERACTION":
                     propertyObj = new WFActivityProperty();
                     XmlUtils.XMLToModel(property.ToString(), propertyObj);
                     return new ActiveActivity(uniqueId, propertyObj);
                 case "CONDITION":
                     propertyObj = new WFConditionProperty();
                     XmlUtils.XMLToModel(property.ToString(), propertyObj);
                     return new ConditionActivity(uniqueId, propertyObj);
                 default:
                     return null;
             }

         }

         #endregion

   这是生成xaml的算法。还想说点什么,但是也没有代码了,说啥啊。。 无代码无真相。。 就说点关于自定义节点的问题吧,用flowchart来构图的话,会遇到一个问题,就是并行节点的处理,在我上面的算法当中,是把并行节点开始到并行结束节点之间的节点视作一个FlowNode,但是如果需要并行之后还有并行这些更复杂的工作流节点的话,可以考虑用NativeActivity,下面是我在写动态修改工作流实例的时候在官网上面找到的一些代码,它是一个并行节点的实现,我觉得是一个很重大的发现。

 public sealed class MyParallelActivity : NativeActivity
     {
         Collection<Activity> branches;

         public Collection<Activity> Branches
         {
             get
             {
                 if (this.branches == null)
                 {
                     this.branches = new Collection<Activity>();
                 }
                 return this.branches;
             }
         }

         protected override void Execute(NativeActivityContext context)
         {
             foreach (Activity branch in this.Branches)
             {
                 context.ScheduleActivity(branch);
             }
         }

         protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
         {
             metadata.AllowUpdateInsideThisActivity();
         }

         protected override void UpdateInstance(NativeActivityUpdateContext updateContext)
         {
             // look for new branches that need to be scheduled
             foreach (Activity branch in this.Branches)
             {
                 // NativeActivityUpdateContext.IsNewlyAdded looks for children not present in the original (pre-update) activity
                 if (updateContext.IsNewlyAdded(branch))
                 {
                     updateContext.ScheduleActivity(branch);
                 }
             }
         }
     }

  注意Execute方法中的一句话:context.ScheduleActivity(branch);    --->调度执行子活动,看到这一句之后,我确实是很兴奋的,因为之前也想过自己写一个完整的Activity,但是苦于不知道怎么执行它的下一个活动。所以如果想重新实现的朋友请继承NativeActivity来实现,因为除了原生的类型之后,WF只支持NativeActivity动态修改后面的流程。

再想想,还有什么没交代的。。。想到了一个,就是判断条件的,比如switch的这种开关的判断条件,它的判断条件可以是一个CodeActivity<string>,我们可以继承重写一个,然后就可以在Execute方法当中写判断的代码了,这里主要是要用到CodeDom来在运行时动态计算结果。就说这么多了,没代码,什么都讲不清楚了,说了也白说。

  这个故事告诉我,我需要一个保存代码的服务器了。。。

  最后把我残存的那一点代码放出来吧,在CSDN上下载http://download.csdn.net/detail/cenyuhaiwork/5670947

WF追忆的更多相关文章

  1. 转《WF编程》笔记目录

    <WF编程>笔记目录 2008-03-18 09:33 by Windie Chai, 26803 阅读, 49 评论, 收藏, 编辑 WF笔记开始 <WF编程>系列之0 - ...

  2. wf(七)(手把手包会)

    这个demo中我们将用If/Else逻辑加到工作流用来展示不同的message通过自定义的条件. 如果name的字符数是奇数,第一个单词就输出“Greeting”否则输出“Hello”. 1. 在Sa ...

  3. wf(五)

    测试工作流: 运用wf(四)的solution: 创建单元测试项目: 1.选择HelloWorkflow解决方案,右键选择添加新建项目:选择单元测试模板,命名为HelloWorkflow.Tests. ...

  4. wf(四)

    我们已经在c#和xaml上编写了工作流,或者有的人会觉得在xaml上编写的workflow没什么优点,然而其实xaml其实具有一些很特别的优势. 1. xaml支持工作流设计器,c#不支持: 2. x ...

  5. wf(三)

    前言: 到现在我们可以看到,WF4包含一个.xmal 文件的设计器和一个调用活动的runtime.当你创建自己的工作流的时候,你是同时也创建了一个活动, 因为活动是一个继承System.Activit ...

  6. WF(二)

    步骤一: 运用WF(一)中创建好的solution 重命名Workflow1.xaml,变为SayHello.xaml 并在属性窗口设置名称为HelloWorkflow.SayHello,如下图: ( ...

  7. [WF] Quickstart Sample

    [WF] Quickstart Sample 前言 Workflow Foundation(WF),总是给人一种很有用.可是却不知道怎么用的印象.这主要是因为前置的功课太多.要整合很多底层知识,才能完 ...

  8. CS中调用微软自带com组件实现音频视频播放(wf/wpf)

    1.mp3播放器:工具箱中右键,在弹出的菜单中选择“选择项”,添加“com组件”,选择名称“windows Media Player",点击确定就会在工具箱新增一个“windows Medi ...

  9. WF 快速入门

    WF(Windows Workflow Foundation ,中文译为:Windows工作流基础)是一种基于更高级抽象概念的编程语言,适合于实现业务流程.虽然可以通过使用图形化的工具(Workflo ...

随机推荐

  1. 几道比较难的SQL题

    上条记录和下一条记录 在展示博客文章时,在文章底部需要展示上一篇文章和下一篇文章,文章的排序当然是按照时间排序的. 选定下一条时可以用limit 1来实现,选取上一条时可以倒序limit 1实现 (S ...

  2. 【LeetCode】49. Anagrams (2 solutions)

    Anagrams Given an array of strings, return all groups of strings that are anagrams. Note: All inputs ...

  3. 使用Android Ant在编译时混淆

    关于ANT 编译和脚本请查看 : http://sinfrancis.javaeye.com/blog/721582 这里使用的是proguard4.4 ,在原有的ANT脚本上加入以下代码: 定义pr ...

  4. 学习WCF笔记之二

    一.学习文章http://www.cnblogs.com/iamlilinfeng/archive/2012/09/25/2700049.html 二.步骤 学习WFC,按照大神的文章一步步学习,不过 ...

  5. Maven install 报错: Failed to execute goalorg.apache.maven.plugins:maven-gpg-plugin:1.4:sign (sign-art

    执行 Maven install 时报错: Failed to execute goalorg.apache.maven.plugins:maven-gpg-plugin:1.4:sign (sign ...

  6. CentOS7设置自定义开机启动,添加自定义系统服务

    Centos 系统服务脚本目录: /usr/lib/systemd/ 有系统(system)和用户(user)之分,如需要开机没有登陆情况下就能运行的程序,存在系统服务(system)里,即: lib ...

  7. unity 在Game视图中显示Gizmos

    自己画的Gizmos要想在Game视图中能看到,需要把Game视图窗口右上角的"Gizmos"按钮点下去.如图: 比如,下面代码以角色的capsuleCollider中心为中心画一 ...

  8. 在Spring中注入Java集合

    集合注入重要是对数组.List.Set.map的注入,具体注入方法请参照一下代码(重点是applicationContext.xml中对这几个集合注入的方式): 1.在工程中新建一个Departmen ...

  9. electron 的跳转

    // 测试 正常跳转应该登录成功 // that.timer = setInterval(() => { that.$router.push('/mainChat');//路由跳转mainCha ...

  10. vue2.0的常用功能简介

    路由跳转 当我们想要实现点击链接跳转时,可以使用$router来进行跳转 语法如下: '}}) 这里path是要跳转的路径,query里面是路径跳转时要携带的参数,以对象的形式存在 2 获取路由参数 ...