using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace TreeToText
{
class TreeToText
{
const string LineMid = "├─";
const string LineLast = "└─";
const string Line = "│ ";
const string Space = " ";
/// <summary>
/// Convert a tree node to text
/// </summary>
/// <param name="node">Root node to convert</param>
/// <returns>Text</returns>
public static string Tree2Text(TreeNode node)
{
if (node == null) return null;
StringBuilder builder = new StringBuilder();
builder.AppendLine(TreeNodeText(node));
Tree2Text(builder, node, "");
return builder.ToString();
}
static string TreeNodeText(TreeNode node)
{
return node.Text;
}
static void Tree2Text(StringBuilder builder, TreeNode parent, string prefix)
{
int nodesCount = parent.Nodes.Count;
if (nodesCount == 0) return;
int nodeMaxIndex = nodesCount - 1;
for (int i = 0; i < nodesCount; i++)
{
builder.Append(prefix);
TreeNode node = parent.Nodes[i];
if (i != nodeMaxIndex)
{
builder.Append(LineMid);
builder.AppendLine(TreeNodeText(node));
Tree2Text(builder, node, prefix + Line);
}
else
{
builder.Append(LineLast);
builder.AppendLine(TreeNodeText(node));
Tree2Text(builder, node, prefix + Space);
}
}
}
}
}
Tag: dotNet Products
ESXiPXE: Install ESXi from networking
A small tool for deploying VMware ESXi from another computer running with Microsoft Windows.
DotNet framework runtime 4.o is required.
Freeware.
中国IP地址段抽取工具
本工具可以将所有中国的IP v4地址段抽取出来,并按照用户给定的格式保存。
通常可以用于制作特定的路由表。
IP信息来源:每次运行时自动获取自APNIC。
运行需要:dotnet Framework 4.0
运行前,请用文本编辑器打开CNRouteExtractor.exe.config,按照注释修改其中的Format字符串。
运行时的格式:CNRouteExtractor filename
将生成filename作为目标输出文件。如不指定filename则不输出(仅测试下载与抽取)。
Recursive Enumerator
using System;
using System.Collections.Generic;
namespace SecretNest.RecursiveEnumerator
{
/// <summary>
/// Get the enumerator for querying the parents of specified item.
/// </summary>
/// <typeparam name="T">Item type</typeparam>
/// <param name="current">Item for querying parents</param>
/// <returns>Enumerator of parents querying</returns>
public delegate IEnumerator<T> GetParentsEnumerator<T>(T current);
/// <summary>
/// Enumerator for querying parents
/// </summary>
/// <typeparam name="T">Item type</typeparam>
public class Enumerator<T> : IEnumerator<T>
{
T current, initial;
Queue<T> notQueried = new Queue<T>();
HashSet<T> queried = new HashSet<T>(); //for avoiding duplicated query
Queue<T> rollbackHistory = new Queue<T>(); //for soft reset
Queue<T> history = new Queue<T>(); //for soft reset
IEnumerator<T> activeQuery;
/// <summary>
/// Callback for getting the enumerator, which is used for querying the parents of specified item.
/// </summary>
public GetParentsEnumerator<T> GetParentsEnumeratorCallback { get; set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="initial">Initial item</param>
public Enumerator(T initial)
{
notQueried.Enqueue(initial);
this.initial = initial;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="initial">Initial item</param>
/// <param name="callback">Callback for getting the enumerator, which is used for querying the parents of specified item.</param>
public Enumerator(T initial, GetParentsEnumerator<T> callback)
{
notQueried.Enqueue(initial);
this.initial = initial;
GetParentsEnumeratorCallback = callback;
}
/// <summary>
/// Gets the current element in the collection.
/// </summary>
public T Current
{
get { return current; }
}
bool disposed;
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
current = default(T);
notQueried = null;
queried = null;
history = null;
}
disposed = true;
}
}
/// <summary>
/// Gets the current element in the collection.
/// </summary>
object System.Collections.IEnumerator.Current
{
get { return current; }
}
/// <summary>
/// Skip same items
/// </summary>
public bool SkipSameItems { get; set; }
/// <summary>
/// Advances the enumerator to the next element of the collection.
/// </summary>
/// <returns>true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. </returns>
public bool MoveNext()
{
if (disposed) throw new ObjectDisposedException(null);
if (rollbackHistory.Count > 0)
{
current = rollbackHistory.Dequeue();
history.Enqueue(current);
return true;
}
if (activeQuery != null)
{
here:
if (activeQuery.MoveNext())
{
if (SkipSameItems && history.Contains(activeQuery.Current)) { goto here; }
current = activeQuery.Current;
history.Enqueue(current);
notQueried.Enqueue(current);
return true;
}
else
{
activeQuery = null;
}
}
if (GetParentsEnumeratorCallback != null)
{
while (notQueried.Count != 0)
{
T item = notQueried.Dequeue();
if (!queried.Contains(item))
{
IEnumerator<T> enumerator = GetParentsEnumeratorCallback(item);
queried.Add(item);
here:
if (enumerator != null)
{
if (enumerator.MoveNext())
{
activeQuery = enumerator;
if (SkipSameItems && history.Contains(enumerator.Current)) { goto here; }
current = enumerator.Current;
history.Enqueue(current);
notQueried.Enqueue(current);
return true;
}
else
{
enumerator = null;
}
}
}
}
}
return false;
}
/// <summary>
/// Sets the enumerator to its initial position, which is before the first element in the collection. Keep all histories for caching.
/// </summary>
public void Reset()
{
if (disposed) throw new ObjectDisposedException(null);
while (history.Count > 0)
{
rollbackHistory.Enqueue(history.Dequeue());
}
current = default(T);
}
/// <summary>
/// Sets the enumerator to its initial position, which is before the first element in the collection. Reset all data, and close active sub-query.
/// </summary>
public void HardReset()
{
if (disposed) throw new ObjectDisposedException(null);
queried.Clear();
notQueried.Clear();
notQueried.Enqueue(initial);
history.Clear();
activeQuery = null;
current = default(T);
}
}
}
Chorus Update: Invoke Helper
A new Invoke Helper is added for making it easier with creating subscribers for UI updating job, by calling Invoke method internally.
See Chorus page for more information.
Chorus Update
Performance optimized. Chorus will require little more memory but run much faster.
Document(pdf) error fixed.
No interface / flow changed. You don’t need to adjust your code. Just download the new version and enjoy it.
Chorus本地模式版已经发布
Chorus是一个框架,它实现了多个部件之间的通讯功能。在它的协助下,软件系统中的每个部件可以自由通讯,而不论这些部件运行在同一个程序,同一台计算机,还是在世界的任何角落。
Chorus是一种模型,它展示了软件系统内部的物理结构。在它的支持下,软件系统中的每个部件可以随心拼装,而不论这些部件构造于您的产品,您的企业,还是获取自其他供应商。
Chorus是一份标准,它定义了每个程序部件的接口规格。在它的规范下,软件系统中的每个部件可以严格定义,而不论这些部件开发于同一个员工,同一个小组,还是来自外包公司。
当前已经发布本地模式版,实现同一个应用程序内部的通讯功能。
您有兴趣了解吗?请访问Chorus发布页。