本文整理汇总了C#中HashSet.SelectMany方法的典型用法代码示例。如果您正苦于以下问题:C# HashSet.SelectMany方法的具体用法?C# HashSet.SelectMany怎么用?C# HashSet.SelectMany使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类HashSet
的用法示例。
在下文中一共展示了HashSet.SelectMany方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: GetTransitiveClosure
private IEnumerable<string> GetTransitiveClosure(string state)
{
var result = new HashSet<string> { state };
while (result.Union(result.SelectMany(s => GetTransitions(s, null))).Distinct().Count() != result.Count)
{
result.SelectMany(s => GetTransitions(s, null)).ToArray().ForEach(s => result.Add(s));
}
return result;
}
示例2: BtnAddcheck_Click
private void BtnAddcheck_Click(object sender, RoutedEventArgs e)
{
ScanImportFolders frm = new ScanImportFolders();
frm.Owner = GetTopParent();
bool? result = frm.ShowDialog();
if (result.HasValue && result.Value)
{
this.IsEnabled = false;
Cursor = Cursors.Wait;
Scan s = frm.SelectedScan;
HashSet<int> imp=new HashSet<int>(s.ImportFolderList);
List<VideoLocal> vl=imp.SelectMany(a=>RepoFactory.VideoLocal.GetByImportFolder(a)).Distinct().ToList();
List<ScanFile> files=new List<ScanFile>();
foreach (VideoLocal v in vl)
{
foreach (VideoLocal_Place p in v.Places.Where(a => imp.Contains(a.ImportFolderID)))
{
ScanFile sfile=new ScanFile();
sfile.Hash = v.ED2KHash;
sfile.FileSize = v.FileSize;
sfile.FullName = p.FullServerPath;
sfile.ScanID = s.ScanID;
sfile.Status = (int) ScanFileStatus.Waiting;
sfile.ImportFolderID = p.ImportFolderID;
sfile.VideoLocal_Place_ID = p.VideoLocal_Place_ID;
files.Add(sfile);
}
}
RepoFactory.ScanFile.Save(files);
this.IsEnabled = true;
Scanner.Instance.Scans.Add(s);
comboProvider.SelectedItem = s;
Cursor = Cursors.Arrow;
}
}
示例3: ContiguousAirBuildings
private static IEnumerable<CompAir> ContiguousAirBuildings( Building root, NetLayer layer )
{
closedSet.Clear();
currentSet.Clear();
openSet.Add( root );
do
{
//Move all opened to closed
foreach (var current in openSet)
{
closedSet.Add( current );
}
var tempSet = currentSet;
currentSet = openSet;
openSet = tempSet;
openSet.Clear();
foreach (var things in currentSet.SelectMany( openBuilding =>
GenAdj.CellsAdjacentCardinal( openBuilding )
.Select( openCells => openCells.GetThingList() ) )
)
{
//All adjacent things
foreach (var current in things)
{
var building = current as Building;
var compAir = building?.TryGetComp< CompAir >();
//No adjacent CompAir
if (compAir == null)
{
continue;
}
//CompAir is not on the same layer
if (!compAir.IsLayerOf( layer ))
{
continue;
}
//Already swept through
if (openSet.Contains( building ) ||
currentSet.Contains( building ) ||
closedSet.Contains( building ))
{
continue;
}
openSet.Add( building );
break;
}
}
} while (openSet.Count > 0);
return from b in closedSet
select b.TryGetComp< CompAir >();
}
示例4: GetAllSequenceFileNames
public string[] GetAllSequenceFileNames()
{
// We can't assume where all of the sequence file types will exist, so to provide
// this functionality we will have to do the following:
// Iterate all of the sequence type descriptors and build a set of file types.
HashSet<string> fileTypes = new HashSet<string>();
IEnumerable<ISequenceTypeModuleDescriptor> sequenceDescriptors =
Modules.GetDescriptors<ISequenceTypeModuleInstance, ISequenceTypeModuleDescriptor>();
foreach (ISequenceTypeModuleDescriptor descriptor in sequenceDescriptors) {
fileTypes.Add(descriptor.FileExtension);
}
// Find all files of those types in the data branch.
return
fileTypes.SelectMany(x => Directory.GetFiles(Paths.DataRootPath, "*" + x, SearchOption.AllDirectories)).ToArray();
}
示例5: GetFields
public ReadOnlyCollection<IField> GetFields(bool includeInherited)
{
if (includeInherited && _allFields == null)
{
List<Field> allFields = new List<Field>(GetFields(false).Cast<Field>());
HashSet<ReferenceType> inheritedTypes = new HashSet<ReferenceType>();
GetInheritedTypes(this, inheritedTypes);
allFields.AddRange(inheritedTypes.SelectMany(type => type.GetFields(false)).Cast<Field>());
_allFields = allFields.ToArray();
}
else if (!includeInherited && _fields == null)
{
DeclaredFieldData[] fieldData;
DebugErrorHandler.ThrowOnFailure(VirtualMachine.ProtocolService.GetFields(out fieldData, ReferenceTypeId));
Field[] fields = Array.ConvertAll(fieldData, field => VirtualMachine.GetMirrorOf(this, field));
_fields = fields;
}
return new ReadOnlyCollection<IField>(includeInherited ? _allFields : _fields);
}
示例6: ProcessMap_ValidInput_AllCellsAreReachable
public void ProcessMap_ValidInput_AllCellsAreReachable()
{
var map = GenerateMap();
var visitedCells = new HashSet<Cell>();
var discoveredCells = new HashSet<Cell>() { map.AllCells.FirstOrDefault(cell => cell.Terrain == TerrainType.Floor) };
while (discoveredCells.Any())
{
foreach (var discoveredCell in discoveredCells)
{
visitedCells.Add(discoveredCell);
}
var newDiscoveredCells = new HashSet<Cell>();
foreach (var newDiscoveredCell in discoveredCells.SelectMany(cell => map.GetAllAdjacentCells(cell)
.Where(c => c.Terrain != TerrainType.Rock && !visitedCells.Contains(c))))
{
newDiscoveredCells.Add(newDiscoveredCell);
}
discoveredCells = newDiscoveredCells;
}
var unReachable = map.AllCells.Where(cell => cell.Terrain != TerrainType.Rock).Except(visitedCells).ToList();
Assert.AreEqual(map.AllCells.Count(cell => cell.Terrain != TerrainType.Rock), visitedCells.Count);
}
示例7: ProcessMap_ValidInput_AllCellsAreReachable
public void ProcessMap_ValidInput_AllCellsAreReachable()
{
var map = GenerateMap();
var visitedCells = new HashSet<BinaryCell>();
var discoveredCells = new HashSet<BinaryCell>() { map.GetCell(0, 0) };
while (discoveredCells.Any())
{
foreach (var discoveredCell in discoveredCells)
{
visitedCells.Add(discoveredCell);
}
var newDiscoveredCells = new HashSet<BinaryCell>();
foreach (var newDiscoveredCell in discoveredCells.SelectMany(cell => cell.Sides
.Where(pair => pair.Value && !visitedCells.Contains(map.GetAdjacentCell(cell, pair.Key)))
.Select(pair => map.GetAdjacentCell(cell, pair.Key))))
{
newDiscoveredCells.Add(newDiscoveredCell);
}
discoveredCells = newDiscoveredCells;
}
Assert.AreEqual(map.AllCells.Count(), visitedCells.Count);
}
示例8: GetElements
public static List<CollectionElementToken> GetElements(HashSet<QueryToken> allTokens)
{
return allTokens
.SelectMany(t => t.Follow(tt => tt.Parent))
.OfType<CollectionElementToken>()
.Where(a => a.CollectionElementType.IsElement())
.Distinct()
.OrderBy(a => a.FullKey().Length)
.ToList();
}
示例9: Collapse
/// <summary>
/// Collapse a set of nodes in a given workspace.
/// </summary>
/// <param name="dynamoModel">The current DynamoModel</param>
/// <param name="selectedNodes"> The function definition for the user-defined node </param>
/// <param name="currentWorkspace"> The workspace where</param>
/// <param name="args"></param>
public static void Collapse(DynamoModel dynamoModel, IEnumerable<NodeModel> selectedNodes, WorkspaceModel currentWorkspace, FunctionNamePromptEventArgs args = null)
{
var selectedNodeSet = new HashSet<NodeModel>(selectedNodes);
if (args == null || !args.Success)
{
args = new FunctionNamePromptEventArgs();
dynamoModel.OnRequestsFunctionNamePrompt(null, args);
if (!args.Success)
{
return;
}
}
// Note that undoable actions are only recorded for the "currentWorkspace",
// the nodes which get moved into "newNodeWorkspace" are not recorded for undo,
// even in the new workspace. Their creations will simply be treated as part of
// the opening of that new workspace (i.e. when a user opens a file, she will
// not expect the nodes that show up to be undoable).
//
// After local nodes are moved into "newNodeWorkspace" as the result of
// conversion, if user performs an undo, new set of nodes will be created in
// "currentWorkspace" (not moving those nodes in the "newNodeWorkspace" back
// into "currentWorkspace"). In another word, undo recording is on a per-
// workspace basis, it does not work across different workspaces.
//
UndoRedoRecorder undoRecorder = currentWorkspace.UndoRecorder;
using (undoRecorder.BeginActionGroup())
{
var newNodeWorkspace = new CustomNodeWorkspaceModel(
dynamoModel,
args.Name,
args.Category,
args.Description,
0,
0) { WatchChanges = false, HasUnsavedChanges = true };
var newNodeDefinition = new CustomNodeDefinition(Guid.NewGuid())
{
WorkspaceModel = newNodeWorkspace
};
currentWorkspace.DisableReporting();
#region Determine Inputs and Outputs
//Step 1: determine which nodes will be inputs to the new node
var inputs =
new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
selectedNodeSet.SelectMany(
node =>
Enumerable.Range(0, node.InPortData.Count)
.Where(node.HasConnectedInput)
.Select(data => Tuple.Create(node, data, node.Inputs[data]))
.Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));
var outputs =
new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
selectedNodeSet.SelectMany(
node =>
Enumerable.Range(0, node.OutPortData.Count)
.Where(node.HasOutput)
.SelectMany(
data =>
node.Outputs[data].Where(
output => !selectedNodeSet.Contains(output.Item2))
.Select(output => Tuple.Create(node, data, output)))));
#endregion
#region Detect 1-node holes (higher-order function extraction)
var curriedNodeArgs =
new HashSet<NodeModel>(
inputs.Select(x => x.Item3.Item2)
.Intersect(outputs.Select(x => x.Item3.Item2))).Select(
outerNode =>
{
//var node = new Apply1();
var node = newNodeWorkspace.AddNode<Apply1>();
node.SetNickNameFromAttribute();
node.DisableReporting();
node.X = outerNode.X;
node.Y = outerNode.Y;
//Fetch all input ports
// in order
// that have inputs
//.........这里部分代码省略.........
示例10: Process
private static int Process(Options options)
{
try
{
Console.WriteLine("Start Process!");
// Resolve options
var basePath = Path.GetFullPath(options.Path ?? ".");
var sources =
options.Sources.Where(p => string.IsNullOrWhiteSpace(p) == false &&
p.ToLower().IndexOf(".codegen.cs") == -1)
.Select(p => MakeFullPath(p, basePath))
.ToArray();
var references =
options.References.Where(p => string.IsNullOrWhiteSpace(p) == false)
.Select(p => MakeFullPath(p, basePath))
.ToArray();
var targetDefaultPath = @".\Properties\TrackableData.CodeGen.cs";
var targetPath = MakeFullPath(options.TargetFile ?? targetDefaultPath, basePath);
// Parse sources and extract interfaces
Console.WriteLine("- Parse sources");
var syntaxTrees = sources.Select(
file => CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file)).ToArray();
var interfaceDeclarations = syntaxTrees.SelectMany(
st => st.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>()).ToArray();
// Generate code
Console.WriteLine("- Generate code");
var writer = new TextCodeGenWriter();
var relatedSourceTrees = new HashSet<SyntaxNode>();
// TrackablePoco
var pocoCodeGen = new TrackablePocoCodeGenerator() { Options = options };
foreach (var idecl in interfaceDeclarations)
{
var baseType = idecl.GetGenericBase("TrackableData.ITrackablePoco");
if (baseType != null)
{
var pocoType = baseType.TypeArgumentList.Arguments[0].ToString();
if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), pocoType) == false)
{
throw new Exception($"Invalid base type of ITrackablePoco<{pocoType}>");
}
pocoCodeGen.GenerateCode(idecl, writer);
relatedSourceTrees.Add(idecl.GetRootNode());
}
}
// TrackableContainer
var containerCodeGen = new TrackableContainerCodeGenerator() { Options = options };
foreach (var idecl in interfaceDeclarations)
{
var baseType = idecl.GetGenericBase("TrackableData.ITrackableContainer");
if (baseType != null)
{
var containerType = baseType.TypeArgumentList.Arguments[0].ToString();
if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), containerType) == false)
{
throw new Exception($"Invalid base type of ITrackableContainer<{containerType}>");
}
containerCodeGen.GenerateCode(idecl, writer);
relatedSourceTrees.Add(idecl.GetRootNode());
}
}
// Resolve referenced using
var usingDirectives = new HashSet<string>(relatedSourceTrees.SelectMany(
st => st.DescendantNodes().OfType<UsingDirectiveSyntax>()).Select(x => x.Name.ToString()));
usingDirectives.Add("System");
usingDirectives.Add("System.Collections.Generic");
usingDirectives.Add("System.Reflection");
usingDirectives.Add("System.Runtime.Serialization");
usingDirectives.Add("System.Linq");
usingDirectives.Add("System.Text");
usingDirectives.Add("TrackableData");
foreach (var usingDirective in usingDirectives)
writer.AddUsing(usingDirective);
// Save generated code
Console.WriteLine("- Save code");
if (SaveFileIfChanged(targetPath, writer.ToString()) == false)
Console.WriteLine("Nothing changed. Skip writing.");
return 0;
}
catch (Exception e)
{
//.........这里部分代码省略.........
示例11: Collapse
/// <summary>
/// Collapse a set of nodes in a given workspace. Has the side effects of prompting the user
/// first in order to obtain the name and category for the new node,
/// writes the function to a dyf file, adds it to the FunctionDict, adds it to search, and compiles and
/// places the newly created symbol (defining a lambda) in the Controller's FScheme Environment.
/// </summary>
/// <param name="selectedNodes"> The function definition for the user-defined node </param>
/// <param name="currentWorkspace"> The workspace where</param>
public static void Collapse(IEnumerable<NodeModel> selectedNodes, WorkspaceModel currentWorkspace, FunctionNamePromptEventArgs args=null)
{
var selectedNodeSet = new HashSet<NodeModel>(selectedNodes);
if (args == null || !args.Success)
{
args = new FunctionNamePromptEventArgs();
dynSettings.Controller.DynamoModel.OnRequestsFunctionNamePrompt(null, args);
//if (!dynSettings.Controller.DynamoViewModel.ShowNewFunctionDialog(ref newNodeName, ref newNodeCategory))
if (!args.Success)
{
return;
}
}
var newNodeWorkspace = new CustomNodeWorkspaceModel(args.Name, args.Category, args.Description, 0, 0)
{
WatchChanges = false,
HasUnsavedChanges = true
};
var newNodeDefinition = new FunctionDefinition(Guid.NewGuid())
{
WorkspaceModel = newNodeWorkspace
};
currentWorkspace.DisableReporting();
#region Determine Inputs and Outputs
//Step 1: determine which nodes will be inputs to the new node
var inputs = new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
selectedNodeSet.SelectMany(
node => Enumerable.Range(0, node.InPortData.Count).Where(node.HasConnectedInput)
.Select(data => Tuple.Create(node, data, node.Inputs[data]))
.Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));
var outputs = new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
selectedNodeSet.SelectMany(
node => Enumerable.Range(0, node.OutPortData.Count).Where(node.HasOutput).SelectMany(
data => node.Outputs[data]
.Where(output => !selectedNodeSet.Contains(output.Item2))
.Select(output => Tuple.Create(node, data, output)))));
#endregion
#region Detect 1-node holes (higher-order function extraction)
var curriedNodeArgs =
new HashSet<NodeModel>(
inputs
.Select(x => x.Item3.Item2)
.Intersect(outputs.Select(x => x.Item3.Item2)))
.Select(
outerNode =>
{
var node = new Apply1();
//MVVM : Don't make direct reference to view here
//MVVM: no reference to view here
//dynNodeView nodeUI = node.NodeUI;
var elNameAttrib =
node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as
NodeNameAttribute;
if (elNameAttrib != null)
{
node.NickName = elNameAttrib.Name;
}
node.GUID = Guid.NewGuid();
//store the element in the elements list
newNodeWorkspace.Nodes.Add(node);
node.WorkSpace = newNodeWorkspace;
node.DisableReporting();
//MVVM : Can't set view location here
//dynSettings.Bench.WorkBench.Children.Add(nodeUI);
//Place it in an appropriate spot
//Canvas.SetLeft(nodeUI, Canvas.GetLeft(outerNode.NodeUI));
//Canvas.SetTop(nodeUI, Canvas.GetTop(outerNode.NodeUI));
node.X = outerNode.X;
node.Y = outerNode.Y;
//Fetch all input ports
// in order
// that have inputs
//.........这里部分代码省略.........
示例12: ParseStfs
private static ObservableCollection<FileEntryViewModel> ParseStfs(StfsPackage package)
{
var collection = new ObservableCollection<FileEntryViewModel>();
var allocatedBlocks = new HashSet<int>();
var blockCollisions = new HashSet<int>();
foreach (var fileEntry in package.FlatFileList.Where(f => !f.IsDirectory).OrderBy(f => f.Name))
{
var blockList = package.GetFileEntryBlockList(fileEntry);
foreach (var block in blockList.Where(b => b.Key.HasValue))
{
if (!allocatedBlocks.Contains(block.Key.Value))
allocatedBlocks.Add(block.Key.Value);
else
blockCollisions.Add(block.Key.Value);
}
collection.Add(new FileEntryViewModel(fileEntry, blockList, package));
}
foreach (var block in blockCollisions.SelectMany(blockCollision => collection.SelectMany(vm => vm.Blocks.Where(b => b.BlockNumber == blockCollision))))
{
block.Health = FileBlockHealthStatus.Collision;
}
return collection;
}
示例13: Process
private static int Process(Options options)
{
try
{
Console.WriteLine("Start Process!");
// Resolve options
var basePath = Path.GetFullPath(options.Path ?? ".");
var sources =
options.Sources.Where(p => string.IsNullOrWhiteSpace(p) == false &&
p.ToLower().IndexOf(".codegen.cs") == -1)
.Select(p => MakeFullPath(p, basePath))
.ToArray();
var references =
options.References.Where(p => string.IsNullOrWhiteSpace(p) == false)
.Select(p => MakeFullPath(p, basePath))
.ToArray();
var targetDefaultPath = @".\Properties\TrackableData.CodeGen.cs";
var targetPath = MakeFullPath(options.TargetFile ?? targetDefaultPath, basePath);
// Parse sources and extract interfaces
Console.WriteLine("- Parse sources");
var syntaxTrees = sources.Select(
file => CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file)).ToArray();
var interfaceDeclarations = syntaxTrees.SelectMany(
st => st.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>()).ToArray();
// Generate code
Console.WriteLine("- Generate code");
var settings = new CodeWriterSettings(CodeWriterSettings.CSharpDefault);
settings.TranslationMapping["`"] = "\"";
var w = new CodeWriter.CodeWriter(settings);
var relatedSourceTrees = new HashSet<SyntaxNode>();
w.HeadLines = new List<string>
{
"// ------------------------------------------------------------------------------",
"// <auto-generated>",
"// This code was generated by TrackableData.CodeGenerator.",
"//",
"// Changes to this file may cause incorrect behavior and will be lost if",
"// the code is regenerated.",
"// </auto-generated>",
"// ------------------------------------------------------------------------------",
"",
"using System;",
"using System.Collections.Generic;",
"using System.Reflection;",
"using System.Runtime.Serialization;",
"using System.Linq;",
"using System.Text;",
"using TrackableData;",
""
};
// TrackablePoco
var pocoCodeGen = new TrackablePocoCodeGenerator() { Options = options };
foreach (var idecl in interfaceDeclarations)
{
var baseType = idecl.GetGenericBase("TrackableData.ITrackablePoco");
if (baseType != null)
{
var pocoType = baseType.TypeArgumentList.Arguments[0].ToString();
if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), pocoType) == false)
{
throw new Exception($"Invalid base type of ITrackablePoco<{pocoType}>");
}
pocoCodeGen.GenerateCode(idecl, w);
relatedSourceTrees.Add(idecl.GetRootNode());
}
}
// TrackableContainer
var containerCodeGen = new TrackableContainerCodeGenerator() { Options = options };
foreach (var idecl in interfaceDeclarations)
{
var baseType = idecl.GetGenericBase("TrackableData.ITrackableContainer");
if (baseType != null)
{
var containerType = baseType.TypeArgumentList.Arguments[0].ToString();
if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), containerType) == false)
{
throw new Exception($"Invalid base type of ITrackableContainer<{containerType}>");
}
containerCodeGen.GenerateCode(idecl, w);
relatedSourceTrees.Add(idecl.GetRootNode());
}
}
// Resolve referenced using
//.........这里部分代码省略.........
示例14: Visit
/// <summary>
/// Visit the given context and return a collection of the resultant contexts.
/// </summary>
/// <returns>Zero or more <see cref="IRenderingContext"/> instances, determined by the outcome of this visit.</returns>
/// <param name="context">The rendering context to visit.</param>
public override IRenderingContext[] Visit(IRenderingContext context)
{
if(context == null)
{
throw new ArgumentNullException(nameof(context));
}
IEnumerable<IRenderingContext>
output = new [] { context },
newlyExposedElements = new RenderingContext[0];
var macroAttribute = context.Element.GetMetalAttribute(ZptConstants.Metal.DefineMacroAttribute);
if(macroAttribute != null)
{
context.TalModel.AddLocal(MACRONAME, macroAttribute.Value);
}
foreach(var handler in _handlers)
{
var handlingResult = new HashSet<AttributeHandlingResult>();
foreach(var ctx in output)
{
var processedBatch = handler.Handle(ctx);
handlingResult.Add(processedBatch);
}
newlyExposedElements = newlyExposedElements.Union(handlingResult.SelectMany(x => x.NewlyExposedContexts));
output = handlingResult.Where(x => x.ContinueHandling).SelectMany(x => x.Contexts).ToArray();
}
output = output.Union(newlyExposedElements.SelectMany(x => this.Visit(x)));
return output.ToArray();
}
示例15: ConvertToGraphvizDot
private string ConvertToGraphvizDot(Graph graph)
{
Func<string, string> toName = id => id.Substring(id.LastIndexOf('.') + 1);
var tab = " ";
var sb = new StringBuilder();
sb.AppendLine("digraph G {");
int i = 0;
var renderedMessages = new Dictionary<string, int>();
foreach (var handler in graph.Handlers.Values.OrderByDescending(e => e.IsAggregate))
{
Func<string, string> correctId = id =>
{
int count;
if (renderedMessages.TryGetValue(id, out count))
return id + "_" + (count + 1);
return id + "_1";
};
sb.AppendFormat(tab + "subgraph cluster_{0} {{", ++i).AppendLine();
sb.AppendFormat(tab + tab + "label = \"{0}\";", toName(handler.Id)).AppendLine();
sb.AppendLine(tab + tab + "node [style=filled, shape=record];");
var links = new HashSet<Link>();
foreach (var input in handler.Roots)
{
var flow = new List<Message> { input };
flow.AddRange(input.Result);
for (int j = 0; j < flow.Count - 1; j++)
{
if (j + 1 < flow.Count)
links.Add(new Link { From = flow[j], To = flow[j + 1] });
}
}
foreach (var link in links)
sb.AppendFormat(tab + tab + "\"{0}\" -> \"{1}\"", correctId(link.From.Id), correctId(link.To.Id)).AppendLine();
// set message colors
var allMessages = handler.Roots.SelectMany(e => e.Result).Distinct().ToList();
allMessages.AddRange(handler.Roots);
foreach (var cmd in allMessages.Where(e => e.IsCommand))
sb.AppendFormat(tab + tab + "\"{0}\"[color=lightblue, label=\"{1}\"];", correctId(cmd.Id), toName(cmd.Id)).AppendLine();
foreach (var evt in allMessages.Where(e => e.IsEvent))
sb.AppendFormat(tab + tab + "\"{0}\"[color=orange, label=\"{1}\"];", correctId(evt.Id), toName(evt.Id)).AppendLine();
sb.AppendLine(tab + "}");
foreach (var msg in links.SelectMany(e => new[] { e.From, e.To }).Distinct())
{
int count;
renderedMessages.TryGetValue(msg.Id, out count);
renderedMessages[msg.Id] = ++count;
}
}
foreach (var kv in renderedMessages.Where(kv => kv.Value > 1))
{
int count = kv.Value;
for (int j = 0; j < count - 1; j++)
for (int k = j + 1; k < count; k++)
sb.AppendFormat(tab + "\"{0}_{1}\" -> \"{0}_{2}\"[style=dotted, color=grey, arrowsize=0];", kv.Key, j + 1, k + 1).AppendLine();
//for (int j = 1; j < count; j++)
// sb.AppendFormat(tab + "\"{0}_1\" -> \"{0}_{1}\"[style=dotted, color=grey, arrowsize=0];", kv.Key, j + 1).AppendLine();
}
sb.AppendLine("}");
return sb.ToString();
}