아래 클래스는 Tree Item 을 표현하였다.
public class TreeItem { public TreeItem Before { get; private set; } private readonly List<TreeItem> nexts = new List<TreeItem>(); public IEnumerable<TreeItem> Nexts => this.nexts; public string Name { get; } public TreeItem(string name) { this.Name = name; } public void AddNext(TreeItem item) { this.nexts.Add(item); item.Before = this; } public IEnumerable<TreeItem> BeforeStream() { // } public IEnumerable<TreeItem> NextStream() { // } }
Before는 부모 노드 이며 Nexts 자식 노드들이다.
메서드 BeforeStream() 은 모든 부모들을 검색한다.
메서드 NextStream() 은 모든 자식들을 검색한다.
이 두 메서드를 지연 반환(yield return)을 이용하여 작성 하고 아래와 같은 결과를 출력한다.
public static void Test() { TreeItem root = new TreeItem("root"); TreeItem level1 = new TreeItem("level1"); TreeItem level2 = new TreeItem("level2"); TreeItem level1_1 = new TreeItem("level1_1"); TreeItem level1_2 = new TreeItem("level1_2"); TreeItem level2_1 = new TreeItem("level2_1"); TreeItem level2_2 = new TreeItem("level2_2"); TreeItem level2_3 = new TreeItem("level2_3"); root.AddNext(level1); root.AddNext(level2); level1.AddNext(level1_1); level1.AddNext(level1_2); level2.AddNext(level2_1); level2.AddNext(level2_2); level2.AddNext(level2_3); Console.WriteLine("root nexts:"); foreach (var item in root.NextStream()) { Console.WriteLine(item.Name); } Console.WriteLine(); Console.WriteLine("level1_2 befores:"); foreach (var item in level1_2.BeforeStream()) { Console.WriteLine(item.Name); } var found = root.NextStream().First(i => i.Name == "level1_1"); Console.WriteLine(""); Console.WriteLine("found:"); Console.WriteLine(found.Name); }
결과:
root nexts:
level1
level1_1
level1_2
level2
level2_1
level2_2
level2_3
level1_2 befores:
level1
root
found:
level1_1
#2
작성한 두 메서드(BeforeStream, NextStream)를 다른 곳 에서도 사용 할 수 있도록 하자.
아래와 같이 조직도를 표현하기 위한 Group(조직) 이라는 Entity 가 있다.
Group은 GroupBase라는 클래스를 상속 받고 있으므로 해당기능은 인터페이스로 정의하고 확장메서드를 이용하여 작성한다. 작성한 인터페이스를 Group에 적용 시킨다. (결과는 #1과 동일)
public class GroupBase { } public class Group : GroupBase { public Group Before { get; private set; } private readonly List<Group> nexts = new List<Group>(); public IEnumerable<Group> Nexts => this.nexts; public string Name { get; } public Group(string name) { this.Name = name; } public void AddNext(Group group) { this.nexts.Add(group); group.Before = this; } }
/*답*/
ITreeSearch<T> 를 작성하고 이를 확장하여 BeforeStream, NextStream 을 작성하였다.
Group 에 Tree Search 기능 추가.
public class Group : GroupBase, ITreeSearch<Group>
수정 할 수 없는 다른 에셈블리에 아래와 같은 클래스가 있다면
public class ClassInOtherAssembly { public ClassInOtherAssembly Parent { get; } public IEnumerable<ClassInOtherAssembly> Children { get; } }
아래와 같이 기능을 추가 할 수 있다.
public class ClassInOtherAssemblyExt : ClassInOtherAssembly, ITreeSearch<ClassInOtherAssembly> { public ClassInOtherAssembly Before => this.Parent; public IEnumerable<ClassInOtherAssembly> Nexts => this.Children; }
다음은 작성한 ITreeSearch<T>와 TreeSearchExtensions 이다.
public interface ITreeSearch<T> { T Before { get; } IEnumerable<T> Nexts { get; } } public static class TreeSearchExtensions { public static IEnumerable<T> BeforeStream<T>(this ITreeSearch<T> treeSearch) where T : ITreeSearch<T> { var current = treeSearch.Before; while (current != null) { yield return current; current = current.Before; } } public static IEnumerable<T> NextStream<T>(this ITreeSearch<T> treeSearch) where T : ITreeSearch<T> { foreach (var next in treeSearch.Nexts) { yield return next; foreach (var item in NextStream(next)) { yield return item; } } } }
제약 조건으로 형식 T 는 ITreeSearch<T> 임을 정의 하여 검색된 Before 와 Next 가 ITreeSearch<T> 임을 나타 내었다.
재사용 가능한 메서드를 Interface 확장을 통해 작성 해 보았다.
댓글 없음:
댓글 쓰기