C# reverse navigation with generic types - c#

My classes are similar to these:
public class Root<TChild>
{
int ID {get;}
...
List<TChild> Children {get;}
}
public class Child
{
int IDChild {get;}
...
}
I need to add the reverse navigation property in Child class to access from Child its Root, but I don't know how to declare the property of Root<TChild> type.
Which type should be TChild in Child class?

I tried this in .net fiddle and seems to work just fine
public class Root<TChild>
{
int ID {get;}
List<TChild> Children { get; set; }
}
public class Child
{
int IDChild {get;}
Root<Child> MyRoot { get; set; }
}
// wherever
var root = new Root<Child> { Children = new List<Child>() };
root.Children.Add(new Child { MyRoot = root });

This works fine and problem is that you have two classes for same entry better is use one class for every entry in tree.
public class TreeEntity
{
private int id = 0;
private TreeEntity parent = null;
private IList<TreeEntity> childs = new List<TreeEntity>();
public TreeEntity(int id)
{
this.id = id;
}
public void AddChild(TreeEntity child)
{
childs.Add(child);
child.parent = this;
}
}
or maybe
public class TreeEntity<T>
{
private int id = 0;
private TreeEntity<T> parent = null;
private IList<TreeEntity<T>> childs = new List<TreeEntity<T>>();
private T data = null;
public TreeEntity(int id, T data)
{
this.id = id;
this.data = data;
}
public void AddChild(TreeEntity<T> child)
{
childs.Add(child);
child.parent = this;
}
}
however in your case
public class Root<TChild>
{
int ID {get;}
...
List<TChild> Children {get;}
...
public void addChild(T child)
{
Children.add(child)
child.setParent(this)
}
}
public class Child
{
int IDChild {get;}
Root<Child> parent;
...
public void setParent (Root<Child>)
{
this.parent = parent;
}
}

Related

Implementing IEnumerable for Leaf Nodes of Composite Pattern

I've implemented the composite pattern as follows
public interface IComponent
{
string Name { get; }
}
public interface IComposite : IComponent
{
void AddRange(IEnumerable<IComponent> components);
}
public interface ILeaf : IComponent
{
string Content { get; }
string Parent { get; }
}
public class Composite : IComposite
{
// return an iterator?
private readonly List<IComponent> _children = new List<IComponent>();
public Composite(string name)
{
Name = name;
}
public string Name { get; }
public void AddRange(IEnumerable<IComponent> components)
{
_children.AddRange(components);
}
}
public class Leaf : ILeaf
{
public string Name { get; }
public string Content { get; }
public string Parent { get; }
public Leaf(string name, string content, string parent)
{
Name = name;
Content = content;
Parent = parent;
}
}
I've populated the composite from an xml file as follows
var collection = XElement.Load(#"C:\somexml.xml");
var composite = CreateComposite(collection);
where
public IComponent CreateComposite(XElement element)
{
if (!element.HasElements)
return new Leaf(element.Name.LocalName, element.Value, element.Parent.Name.LocalName);
var composite = new Composite(element.Name.LocalName);
composite.AddRange(element.Elements().Select(CreateComposite));
return composite;
}
This populates my composite as expected - great! However, I'd now like my composite to return an iterator via the implementation of IEnumerable. So I tried this
public class Composite : IComposite, IEnumerable<IComponent>
{
// return an iterator?
private readonly List<IComponent> _children = new List<IComponent>();
public Composite(string name)
{
Name = name;
}
public string Name { get; }
public void AddRange(IEnumerable<IComponent> components)
{
_children.AddRange(components);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<IComponent> GetEnumerator()
{
foreach (var child in _children)
{
yield return child;
}
}
}
But this only iterates through the top level of components, i.e., any components nested within _children are not returned. How do I update this to recursively iterate through all components?
You can iterate recursively like this (it will do iteration in depth-first manner):
public interface IComposite : IComponent, IEnumerable<IComponent>
{
void AddRange(IEnumerable<IComponent> components);
}
public IEnumerator<IComponent> GetEnumerator()
{
foreach (var child in _children)
{
yield return child;
var composite = child as IComposite;
if (composite != null) {
foreach (var sub in composite) {
yield return sub;
}
}
}
}
If you want to avoid the cast to IComposite - you need to redesign your interfaces and make your Composite to hold a list of another IComposites instead of components. Then ILeft will also become IComposite with dummy implementation.
You could implement the traversal recursively using Linq as follows.
public IEnumerable<IComponent> GetSuccessors()
{
return _children
.Concat(_children.SelectMany(iChild => iChild.GetSuccessors());
}
If depht-first traversal is desired, you can use the following implementation.
public IEnumerable<IComponent> GetSuccessors()
{
return _children
.SelectMany(iChild => new IComponent[]{iChild}.Concat(iChild.GetSuccessors()));
}
Or, if you need it using your initial syntax, you could use the following.
public IEnumerator<IComponent> GetEnumerator()
{
var Successors
= _children
.SelectMany(iChild => new IComponent[]{iChild}.Concat(iChild.GetSuccessors()));
foreach (var iSuccessor in Successors)
{
yield return iSuccessor;
}
}

Iterate throuh list to determine hierarchy level of elements

There is a List of items which contain a field called "HierarchyLevel" (type of String) which determines the hierarchy of elements like this: Link to image.
The tree structure would look like this:
<ul>
<li>1</li>
<ul>
<li>1.01</li>
<ul>
<li>1.01.01</li>
<li>1.01.02</li>
</ul>
<li>1.02</li>
<ul>
<li>1.02.01</li>
</ul>
<li>1.03</li>
</ul>
<ul>
And so on.
My goal is to implement a class which would contain the information about parent and children of each element.
So far I have this class:
class TreeNode<DBItem>
{
public DBItem Value { get; private set; }
public List<TreeNode<DBItem>> Children = new List<TreeNode<DBItem>>();
public TreeNode<DBItem> Parent { get; private set; }
public string Level { get; private set; }
public TreeNode (DBItem item, string level)
{
this.Value = item;
this.Level = level;
}
public TreeNode<DBItem> this[int i]
{
get { return this.Children[i]; }
}
public TreeNode<DBItem> AddChild(DBItem item, string level)
{
TreeNode<DBItem> node = new TreeNode<DBItem>(item, level) { Parent = this };
this.Children.Add(node);
return node;
}
}
The problem is I don't quite understand how to iterate through the collection of items. I tried this:
TreeNode<DBItem> parent = new TreeNode<DBItem>(neededItems[0], "1");
foreach (var doc in neededItems)
{
string level = doc.GetStringValue("HierarchyLevel");
if (level.StartsWith("1.")&& level.Length < 5)
{
var child1 = parent.AddChild(doc, level);
foreach (var child in neededItems)
{
string level1 = child.GetStringValue("HierarchyLevel");
if (level1.StartsWith("1."+level))
{
child1.AddChild(child, level1);
}
}
}
}
But obviously it is a bad approach.
I would like to get some help and advices on how to iterate through the list correctly.
We can achieve this using:
a Dictionary of all items (to help look-up parent nodes)
a List of root nodes (in case there is more than 1 root)
a list of DBItem objects that is ordered by hierarchy depth (1 before 1.01)
Sample implementation:
class so43271922
{
public so43271922()
{
}
[DebuggerDisplay("HierarchyLevel = {HierarchyLevel}")]
public class DBItem
{
public string Name { get; private set; }
public string HierarchyLevel { get; private set; }
public DBItem(string name, string hierarchyLevel)
{
this.Name = name;
this.HierarchyLevel = hierarchyLevel;
}
}
// Dummy list of DB Item objects
public readonly DBItem[] listItems = new DBItem[] {
new DBItem("Element 1", "1"),
new DBItem("Element 1.01", "1.01"),
new DBItem("Element 1.01.01", "1.01.01"),
new DBItem("Element 1.01.02", "1.01.02"),
new DBItem("Element 1.02", "1.02"),
new DBItem("Element 1.02.01", "1.02.01"),
new DBItem("Element 1.03", "1.03")
};
[DebuggerDisplay("HierarchyLevel = {Value.HierarchyLevel}")]
public class Node
{
public static IReadOnlyDictionary<string,Node> AllNodes { get { return allNodes; } }
public static IReadOnlyCollection<Node> Roots { get { return roots; } }
/// <summary>
/// Stores references to all nodex, using HierarchyLevel as key
/// </summary>
private static Dictionary<string, Node> allNodes = new Dictionary<string, Node>();
/// <summary>
/// Stores references to root nodes
/// </summary>
private static List<Node> roots = new List<Node>();
public DBItem Value { get; private set; }
public Node Parent { get; private set; }
public List<Node> Children { get; private set; }
public int Level { get; private set; }
public Node(DBItem li)
{
this.Children = new List<Node>();
this.Value = li;
allNodes.Add(li.HierarchyLevel, this);
if (li.HierarchyLevel.Contains("."))
{
var parentHier = li.HierarchyLevel.Substring(0, li.HierarchyLevel.LastIndexOf("."));
this.Parent = allNodes[parentHier];
this.Parent.Children.Add(this);
this.Level = this.Parent.Level + 1;
}
else
{
roots.Add(this);
this.Parent = null;
this.Level = 0;
}
}
}
public void generateHierarchy()
{
// Sort all items by: hierarchy depth, then by hierarchy level value
var sortedItems = listItems
.OrderBy(i => i.HierarchyLevel.Count(c => c == '.')); // 1 before 1.01
foreach (var item in sortedItems)
{
new Node(item);
}
var hier = Node.Roots;
}
}

Adding an instance to reference that is field in another instance

Excuse me, this question maybe exist in a different form but I really searched everywhere and don't see it.
I have worked in C++ and am used to pointers. I am having problem with substituting my logic with C# analogue code.
Here is my C# code:
class Parent
{
public Parent A { get; set; }
public Parent B { get; set; }
}
static void Main(string[] args)
{
Parent P1 = new Parent();
Parent X = new Parent();
Parent[] array = new Parent[10];
array[0] = P1;
array[1] = P1.A;
array[2] = P1.B;
array[1]= X;
//I expect P1.A to be X but it is null
}
I have seen that there are pointers in C# but is there a better way to do this? Thanks
Edit:
My question wasn't complete. I am sorry. This is the code:
abstract class Parent
{
protected virtual int foo();
}
public class Son : Parent
{
public Parent A { get; set; }
public Parent B { get; set; }
protected override int foo()
{
return base.foo();
}
}
public class Daughter : Parent
{
public Parent A { get; set; }
public Parent B { get; set; }
}
static void Main(string[] args)
{
Son P1 = new Son();
Parent X = new Daughter();
Parent[] array = new Parent[10];
array[0] = P1;
array[1] = P1.A;
array[2] = P1.B;
array[1]= X;
//I expect P1.A to be X but it is null
}
What you wan t to do is:
array[1].A = X;
It is null because it isn't initialized.
You must initialize properties.
class Parent
{
public Parent A { get; set; }
public Parent B { get; set; }
Parent(Parent a, Parent b)
{
A = a;
B = b;
}
}
and
Parent X = new Parent();
Parent P1 = new Parent(X, new Parent());

Implementing tree structure on c#

I have an object myBook.
Can I implement a better structure for that kind of data?
public class myRow{
public int ID = 0;
public int number = 0;
public String param1 = null;
public decimal param2 = null;
public string parm3 = "";
public int param4 = null;
}
public class mySubChapter{
public int ID = 0;
public string title = "";
public List<myRow> rows;
internal bool sort(){...} //sort rows by ID
}
public class myChapter{
public int ID = 0;
public string title = "";
public List<mySubChapter> subChapters;
internal bool sort(){...} //sort subChapters by ID
}
public class myBook{
public int ID = 0;
public string title = ""
public List<myChapter> chapters;
internal bool sort(){...} //sort chapters by ID
}
If you really want to model your book structure in a tree, you could use a generic tree implementation like the one presented here. Then, you could form a tree using code like this
DTreeNode<string> root = new DTreeNode<string>();
DTreeNode<string> temp;
temp = root.Nodes.Add("Hello");
temp.Nodes.Add("olleH");
temp = root.Nodes.Add("World");
temp.Nodes.AddRange(new string[]
{ "dWorl", "ldWor", "rldWo", "orldW" } );
In my opinion, I'll merge subchapter and chapper class into one myChaper class and add new property is chapterLevel in it. Because I think subChapter is a chapter too with just difference level(children of chapter may be). Sorry for my English.
public class myRow{
public int ID = 0;
public int number = 0;
public String param1 = null;
public decimal param2 = null;
public string parm3 = "";
public int param4 = null;
}
public class myChapter{
public int ID = 0;
public string title = "";
public int chapterLevel = 0;
internal bool sort(){...} //sort chapters by ID and level
}
public class myBook{
public int ID = 0;
public string title = ""
public List<myChapter> chapters;
internal bool sort(){...} //sort chapters by ID
}
Another tree implementation:
public interface INode
{
int Id { get; set; }
INode Parent { get; }
ReadOnlyCollection<INode> Children { get; }
void SetParent(INode node);
void AddChild(INode node);
}
public class Node : INode
{
private INode _parent;
private IList<INode> _children;
public Node()
{
_children = new List<INode>();
}
public int Id { get; set; }
public INode Parent
{
get { return _parent; }
}
public ReadOnlyCollection<INode> Children
{
get
{
return new ReadOnlyCollection<INode>
(_children.OrderBy(c => c.Id).ToList());
}
}
public virtual void AddNode(INode node)
{
_children.Add(node);
node.SetParent(this);
}
public virtual void SetParent(INode node)
{
_parent = node;
}
}
The classes, Row, Chapter, Book can derive from the Node class, e.g.
public class Book : Node
{
public override void SetParent(INode node)
{
throw new InvalidOperationException();
}
public string Title { get; set; }
}

How can WindsorContainer TypedFactory pass arguments to indirect objects

I know that TypedFactory facility will only pass the given arguments to the object it is resolving. But is there a way to make the same arguments be passed down to all indirect objects being resolved?
I've been trying to do this with a Custom Scope defined as
public class ArgumentPassThrough : IScopeAccessor
{
private static IDictionary _args;
public void Dispose()
{
_args = null;
}
public ILifetimeScope GetScope(CreationContext context)
{
var h = context.Handler;
if (_args == null)
{
_args = context.AdditionalArguments;
}
else
{
var enumerator = _args.GetEnumerator();
enumerator.Reset();
while (enumerator.MoveNext())
{
if (!context.AdditionalArguments.Contains(enumerator.Key))
{
context.AdditionalArguments.Add(enumerator.Key, enumerator.Value);
}
}
}
return new DefaultLifetimeScope();
}
}
I have the following class structure:
public class Child2
{
public Child2(Child1 child1)
{
Child1 = child1;
}
public Child1 Child1 { get; private set; }
}
public class Child1
{
public Child1()
{
}
}
public class Parent
{
public Parent(Child1 child1, Child2 child2)
{
Child1 = child1;
Child2 = child2;
}
public Child1 Child1 { get; private set; }
public Child2 Child2 { get; private set; }
}
public interface IParentFactory
{
Parent Create(Child1 child1);
}
I register them in the windsorcontainer with:
public void ScopedFactory()
{
_container.Register(
Component.For<IParentFactory>().AsFactory(),
Component.For<Parent>().LifestyleScoped<ArgumentPassThrough>(),
Component.For<Child2>().LifestyleScoped<ArgumentPassThrough>(),
Classes.FromThisAssembly().Pick()
.WithService.Self()
.LifestyleTransient()
);
}
and I'm using it like:
[Test]
public void ScopedFactoryDependency()
{
_demoModule.ScopedFactory();
var fac = _container.Resolve<IParentFactory>();
var p1 = AssertPassThrough(fac);
var p2 = AssertPassThrough(fac);
Assert.AreNotSame(p1,p2);
}
private Parent AssertPassThrough(IParentFactory fac)
{
Parent parent;
var c1 = _container.Resolve<Child1>();
using (_container.BeginScope())
{
parent = fac.Create(c1);
Assert.AreSame(parent.Child1, c1);
Assert.AreSame(parent.Child2.Child1, c1);
}
return parent;
}
The first pass works, but I was expecting the ScopeAccesor to be disposed when _contaier.BeginScope() exists the using block. This dosen't happen, and the second pass will get the same arguments as the first.

Categories

Resources