Bertiooo.Traversal 1.0.9

dotnet add package Bertiooo.Traversal --version 1.0.9
NuGet\Install-Package Bertiooo.Traversal -Version 1.0.9
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bertiooo.Traversal" Version="1.0.9" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Bertiooo.Traversal --version 1.0.9
#r "nuget: Bertiooo.Traversal, 1.0.9"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Bertiooo.Traversal as a Cake Addin
#addin nuget:?package=Bertiooo.Traversal&version=1.0.9

// Install Bertiooo.Traversal as a Cake Tool
#tool nuget:?package=Bertiooo.Traversal&version=1.0.9

Bertiooo's Traversal Library

This C# lightweight library provides extension methods to traverse hierarchy structures. It may work for other graph types as well.

It targets .Net Standard 2.0, which means you can use it with .NET Core and .NET Framework.

If you like this framework, I appreciate any donations on my PayPal account.

Usage

Install the nuget package

See https://www.nuget.org/packages/Bertiooo.Traversal/

Implement the ITraversable<T> interface

In order to use the extension methods, you need a node class implementing the ITraversable<T> interface.

public class Node : ITraversable<Node> 
{
  public Node Parent { get; }
  public IEnumerable<Node> Children { get; }
}

Sometimes you will find it difficult to implement this interface, either because the property names of your class do not fit or because the collection type of the children property differs from IEnumerable<T>. In this case, it is recommended to use an adapter as described in How to adapt to ITraversable.

Use the extension methods

Here are some examples:

Extension methods for node analysis
Node node = new Node();

bool result;

result = node.IsRoot();
result = node.IsInnerNode();
result = node.IsLeaf();

result = node.HasParent(); 
result = node.HasChildren();
result = node.HasSiblings();

Node other = new Node();

result = node.IsChildOf(other);
result = node.IsParentOf(other);
result = node.IsSiblingOf(other);
result = node.IsDescendantOf(other);
result = node.IsAncestorOf(other);

int result;

result = node.GetLevel();
result = node.GetMaxDepth();
Node result;

result = node.Root();

IEnumerable<Node> result;

result = node.WithParent();
result = node.WithChildren();
result = node.Siblings();
result = node.WithSiblings();
result = node.Descendants();
result = node.WithDescendants();
result = node.Ancestors();
result = node.WithAncestors();
result = node.Leaves();
result = node.InnerNodes();
Traverse extensions
Action<Node> action = n => n.DoSomething();

node.Traverse(action); // per default depth first traversal
node.Traverse(action, TraversalMode.BreadthFirst);

CancellationToken token;
await node.TraverseAsync(action, cancellationToken: token);

IComparer<Node> customComparer = new CustomComparer();
node.Traverse(action, comparer);

ICandidateSelector<Node> customSelector = new CustomCandidateSelector();
node.Traverse(action, customSelector);

See How to change the traversal order for more details about how to influence the order in which the nodes will be traversed.

Use the fluent API

For further control over the traversal process, use the fluent API.

ITraverser<Node> traverser = node.Traverse()
	.Use(TraversalMode.BreadthFirst) // per default depth-first traversal
	.Use(candidateSelector)
	.ReverseOrder()
	.Use(cancellationToken)
	.Skip(someNode) 
	.Ignore(someNodes)
	.Exclude(tmpNode => tmpNode.IsLeaf())
	.DisableCallbacksFor<SubNode>()
	.CancelIf(tmpNode => someCondition())
	.WithAction(tmpNode => action(tmpNode))
	.Prepare(action)
	.Catch<InvalidOperationException>(e => Debug(e))
	.OnCanceled(action)
	.OnSuccess(action)
	.Finish(action)
	.Clone();

See Difference between Skip, Exclude, Ignore and DisableCallbacksFor for more information about those methods.

Then you have different options to execute the traversal:

// Execute() does not return a value
traverser.Execute();
await traverser.ExecuteAsync();

// Be careful: Invoking GetNodes() alone won't cause the traverser to perform the traversal.
// You need to iterate the nodes in order to proceed with the traversal.
// In order to execute the complete traversal consider using ToList() after GetNodes()
IEnumerable<Node> nodes = traverser.GetNodes();

// The async method in contrast will turn the enumerable into a list by full traversal.
IList<Node> nodes = await traverser.GetNodesAsync();
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.9 102 1/19/2024
1.0.8 96 1/12/2024
1.0.7 78 1/9/2024
1.0.6 79 1/9/2024
1.0.5 96 1/8/2024
1.0.4 100 1/6/2024
1.0.3 81 1/6/2024
1.0.2 101 1/6/2024
1.0.1 115 1/6/2024
1.0.0 92 1/6/2024

+ Changed default parameter throwException of API method Catch to value false
+ Bugfix TraversableAdapter while removing obsolete adapters from cache
+ Changed order of adding child nodes to selector and yielding visited node
+ Added Clone API to Traverser
+ Multiple starting nodes for traversal
+ Reset candidate selector after traversal
+ Renamed extension GetRoot to Root
+ Added extensions for parent and children retrieval
+ Removed unnecessary class constraints
+ Added DisableReset API to disable reset of candidate selector before and after each traversal
+ Narrowed some extensions to interfaces