private GraphLink GetOrCreateEventLink(GraphNode source, GraphNode target, EventInfo e) { GraphLink link = null; lock (this.Inbox) { string label = this.GetEventLabel(e.Event); var index = this.GetLinkIndex(source, target, label); var category = GetEventCategory(e.Event); link = this.Graph.GetOrCreateLink(source, target, index, label, category); if (this.MergeEventLinks) { if (link.AddListAttribute("EventIds", e.Event) > 1) { link.Label = "*"; } } else { link.AddAttribute("EventId", e.Event); if (e.HandlingState != null) { link.AddAttribute("HandledBy", e.HandlingState); } } } return(link); }
/// <summary> /// Return all events represented by this link. /// </summary> private static IEnumerable <string> GetEventIds(GraphLink link) { if (link.AttributeLists != null) { // a collapsed edge graph if (link.AttributeLists.TryGetValue("EventIds", out HashSet <string> idList)) { return(idList); } } // a fully expanded edge graph has individual links for each event. if (link.Attributes.TryGetValue("EventId", out string eventId)) { return(new string[] { eventId }); } return(Array.Empty <string>()); }
/// <summary> /// Get existing link or create a new one connecting the given source and target nodes. /// </summary> /// <returns>The new link or the existing link if it was already defined.</returns> public GraphLink GetOrCreateLink(GraphNode source, GraphNode target, int?index = null, string linkLabel = null, string category = null) { string key = source.Id + "->" + target.Id; if (index.HasValue) { key += string.Format("({0})", index.Value); } if (!this.InternalLinks.TryGetValue(key, out GraphLink link)) { link = new GraphLink(source, target, linkLabel, category); if (index.HasValue) { link.Index = index.Value; } this.InternalLinks.Add(key, link); } return(link); }
/// <summary> /// Serialize the graph to DGML. /// </summary> public void WriteDgml(TextWriter writer, bool includeDefaultStyles) { writer.WriteLine("<DirectedGraph xmlns='{0}'>", DgmlNamespace); writer.WriteLine(" <Nodes>"); if (this.InternalNodes != null) { List <string> nodes = new List <string>(this.InternalNodes.Keys); nodes.Sort(); foreach (var id in nodes) { GraphNode node = this.InternalNodes[id]; writer.Write(" <Node Id='{0}'", node.Id); if (!string.IsNullOrEmpty(node.Label)) { writer.Write(" Label='{0}'", node.Label); } if (!string.IsNullOrEmpty(node.Category)) { writer.Write(" Category='{0}'", node.Category); } node.WriteAttributes(writer); writer.WriteLine("/>"); } } writer.WriteLine(" </Nodes>"); writer.WriteLine(" <Links>"); if (this.InternalLinks != null) { List <string> links = new List <string>(this.InternalLinks.Keys); links.Sort(); foreach (var id in links) { GraphLink link = this.InternalLinks[id]; writer.Write(" <Link Source='{0}' Target='{1}'", link.Source.Id, link.Target.Id); if (!string.IsNullOrEmpty(link.Label)) { writer.Write(" Label='{0}'", link.Label); } if (!string.IsNullOrEmpty(link.Category)) { writer.Write(" Category='{0}'", link.Category); } if (link.Index.HasValue) { writer.Write(" Index='{0}'", link.Index.Value); } link.WriteAttributes(writer); writer.WriteLine("/>"); } } writer.WriteLine(" </Links>"); if (includeDefaultStyles) { writer.WriteLine( @" <Styles> <Style TargetType=""Node"" GroupLabel=""Error"" ValueLabel=""True""> <Condition Expression=""HasCategory('Error')"" /> <Setter Property=""Background"" Value=""#FFC15656"" /> </Style> <Style TargetType=""Node"" GroupLabel=""Actor"" ValueLabel=""True""> <Condition Expression=""HasCategory('Actor')"" /> <Setter Property=""Background"" Value=""#FF57AC56"" /> </Style> <Style TargetType=""Node"" GroupLabel=""Monitor"" ValueLabel=""True""> <Condition Expression=""HasCategory('Monitor')"" /> <Setter Property=""Background"" Value=""#FF558FDA"" /> </Style> <Style TargetType=""Link"" GroupLabel=""halt"" ValueLabel=""True""> <Condition Expression=""HasCategory('halt')"" /> <Setter Property=""Stroke"" Value=""#FFFF6C6C"" /> <Setter Property=""StrokeDashArray"" Value=""4 2"" /> </Style> <Style TargetType=""Link"" GroupLabel=""push"" ValueLabel=""True""> <Condition Expression=""HasCategory('push')"" /> <Setter Property=""Stroke"" Value=""#FF7380F5"" /> <Setter Property=""StrokeDashArray"" Value=""4 2"" /> </Style> <Style TargetType=""Link"" GroupLabel=""pop"" ValueLabel=""True""> <Condition Expression=""HasCategory('pop')"" /> <Setter Property=""Stroke"" Value=""#FF7380F5"" /> <Setter Property=""StrokeDashArray"" Value=""4 2"" /> </Style> </Styles>"); } writer.WriteLine("</DirectedGraph>"); }