Hi all,
I've been trying to write some classes, so when I have a parent-child
relationship, such as with Folders in my application, I don't have to
remember to add a parent reference, as well as adding to the child
collection, eg:
parent.Children.Add(child);
child.Parent = parent;
And I've come up with the below (I've included my test, and three classes).
It seems to work, but I have two questions....
1. Does this look like the best way of doing this?
2. I now want to extend this to support multiple lists (eg, my folders can
contain both folders, and messages. Messages can have child messages, and
therefore have both a parent folder, and a parent message), eg.
folder.ChildFolders // Returns List<TreeItem<Folder>>
folder.Messages // Returns List<TreeItem<Message>>
message.ParentMessage // Returns TreeItem<Message>
message.ParentFolder // Returns TreeItem<Folder>
Or should I create a base class that represents the entire tree (Folders and
Messages)? Though this way, I'd have a single child list, and would need to
add properties, like .ChildFolders, which would filter the .Children list!
I know it looks like a lot of code here, but it's just 3 classes and my
command line test. If you paste it into VS, it'll look dead simple :)
Any thoughts or suggestions?
Thanks,
Danny Tuppeny
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
Test1();
Test2();
}
static void Test1()
{
Folder parent = new Folder();
Folder child = new Folder();
child.Parent = parent;
if (parent.Children.Contains(child))
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
}
static void Test2()
{
Folder parent = new Folder();
Folder child = new Folder();
parent.Children.Add(child);
if (parent == child.Parent)
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
}
}
public class ChildList<T> : List<T>
{
public event EventHandler<ChildListEventArgs<T>> Added;
public event EventHandler<ChildListEventArgs<T>> Removed;
public class ChildListEventArgs<T> : EventArgs
{
public T Item;
public ChildListEventArgs(T item)
{
Item = item;
}
}
public new void Add(T item)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
added(this, new ChildListEventArgs<T>(item));
base.Add(item);
}
public new void AddRange(IEnumerable<T> collection)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
{
foreach (T item in collection)
{
added(this, new ChildListEventArgs<T>(item));
}
}
base.AddRange(collection);
}
public new void Insert(int index, T item)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
added(this, new ChildListEventArgs<T>(item));
base.Insert(index, item);
}
public new void InsertRange(int index, IEnumerable<T> collection)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
{
foreach (T item in collection)
{
added(this, new ChildListEventArgs<T>(item));
}
}
base.InsertRange(index, collection);
}
public new bool Remove(T item)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
removed(this, new ChildListEventArgs<T>(item));
return base.Remove(item);
}
public new void RemoveAll(Predicate<T> match)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
{
foreach (T item in base.FindAll(match))
{
removed(this, new ChildListEventArgs<T>(item));
}
}
base.RemoveAll(match);
}
public new void RemoveAt(int index)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
removed(this, new ChildListEventArgs<T>(base[index]));
base.RemoveAt(index);
}
new void RemoveRange(int index, int count)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
{
foreach (T item in base.GetRange(index, count))
{
removed(this, new ChildListEventArgs<T>(item));
}
}
base.RemoveAt(index);
}
}
public class TreeItem<T>
{
TreeItem<T> parent;
ChildList<TreeItem<T>> children;
public TreeItem()
{
children = new ChildList<TreeItem<T>>();
children.Added += delegate(object sender,
ChildList<TreeItem<T>>.ChildListEventArgs<TreeItem <T>> e) { e.Item.parent =
this; };
children.Removed += delegate(object sender,
ChildList<TreeItem<T>>.ChildListEventArgs<TreeItem <T>> e) { e.Item.parent =
null; };
}
public TreeItem<T> Parent
{
get { return parent; }
set
{
if (parent != value)
{
if (parent != null)
{
// This automagically unsets the internal parent
parent.children.Remove(this);
}
if (value != null)
{
// This automagically sets the internal parent
value.children.Add(this);
}
}
}
}
public ChildList<TreeItem<T>> Children
{
get { return children; }
}
}
public class Folder : TreeItem<Folder>
{
string name;
public Folder()
{
}
public string Name
{
get { return name; }
set { name = value; }
}
}
} 4 4533
um... HOw 'bout a nice simple:
parent.AddChild(child);
where AddChild is defined as
public AddChild(IChild pChild)
{
this.Children.Add(child);
child.Parent = this;
}
--
Truth,
James Curran
[erstwhile VC++ MVP]
Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
"Danny Tuppeny" <gr****@dannytuppeny.commmmmm> wrote in message
news:43***********************@ptn-nntp-reader04.plus.net... Hi all,
I've been trying to write some classes, so when I have a parent-child relationship, such as with Folders in my application, I don't have to remember to add a parent reference, as well as adding to the child collection, eg:
parent.Children.Add(child); child.Parent = parent;
And I've come up with the below (I've included my test, and three
classes). It seems to work, but I have two questions....
1. Does this look like the best way of doing this?
2. I now want to extend this to support multiple lists (eg, my folders can contain both folders, and messages. Messages can have child messages, and therefore have both a parent folder, and a parent message), eg.
folder.ChildFolders // Returns List<TreeItem<Folder>> folder.Messages // Returns List<TreeItem<Message>>
message.ParentMessage // Returns TreeItem<Message> message.ParentFolder // Returns TreeItem<Folder>
Or should I create a base class that represents the entire tree (Folders
and Messages)? Though this way, I'd have a single child list, and would need
to add properties, like .ChildFolders, which would filter the .Children list!
I know it looks like a lot of code here, but it's just 3 classes and my command line test. If you paste it into VS, it'll look dead simple :)
Any thoughts or suggestions?
Thanks,
Danny Tuppeny
namespace MyApplication { class Program { static void Main(string[] args) { Test1(); Test2(); }
static void Test1() { Folder parent = new Folder(); Folder child = new Folder();
child.Parent = parent;
if (parent.Children.Contains(child)) { Console.WriteLine("Test succeeded"); } else { Console.WriteLine("Test failed"); } }
static void Test2() { Folder parent = new Folder(); Folder child = new Folder();
parent.Children.Add(child);
if (parent == child.Parent) { Console.WriteLine("Test succeeded"); } else { Console.WriteLine("Test failed"); } } }
public class ChildList<T> : List<T> { public event EventHandler<ChildListEventArgs<T>> Added; public event EventHandler<ChildListEventArgs<T>> Removed;
public class ChildListEventArgs<T> : EventArgs { public T Item; public ChildListEventArgs(T item) { Item = item; } }
public new void Add(T item) { EventHandler<ChildListEventArgs<T>> added = Added; if (added != null) added(this, new ChildListEventArgs<T>(item));
base.Add(item); }
public new void AddRange(IEnumerable<T> collection) { EventHandler<ChildListEventArgs<T>> added = Added; if (added != null) { foreach (T item in collection) { added(this, new ChildListEventArgs<T>(item)); } }
base.AddRange(collection); }
public new void Insert(int index, T item) { EventHandler<ChildListEventArgs<T>> added = Added; if (added != null) added(this, new ChildListEventArgs<T>(item));
base.Insert(index, item); }
public new void InsertRange(int index, IEnumerable<T> collection) { EventHandler<ChildListEventArgs<T>> added = Added; if (added != null) { foreach (T item in collection) { added(this, new ChildListEventArgs<T>(item)); } }
base.InsertRange(index, collection); }
public new bool Remove(T item) { EventHandler<ChildListEventArgs<T>> removed = Removed; if (removed != null) removed(this, new ChildListEventArgs<T>(item));
return base.Remove(item); }
public new void RemoveAll(Predicate<T> match) { EventHandler<ChildListEventArgs<T>> removed = Removed; if (removed != null) { foreach (T item in base.FindAll(match)) { removed(this, new ChildListEventArgs<T>(item)); } }
base.RemoveAll(match); }
public new void RemoveAt(int index) { EventHandler<ChildListEventArgs<T>> removed = Removed; if (removed != null) removed(this, new ChildListEventArgs<T>(base[index]));
base.RemoveAt(index); }
new void RemoveRange(int index, int count) { EventHandler<ChildListEventArgs<T>> removed = Removed; if (removed != null) { foreach (T item in base.GetRange(index, count)) { removed(this, new ChildListEventArgs<T>(item)); } }
base.RemoveAt(index); } }
public class TreeItem<T> { TreeItem<T> parent; ChildList<TreeItem<T>> children;
public TreeItem() { children = new ChildList<TreeItem<T>>(); children.Added += delegate(object sender, ChildList<TreeItem<T>>.ChildListEventArgs<TreeItem <T>> e) { e.Item.parent
= this; }; children.Removed += delegate(object sender, ChildList<TreeItem<T>>.ChildListEventArgs<TreeItem <T>> e) { e.Item.parent
= null; }; }
public TreeItem<T> Parent { get { return parent; } set { if (parent != value) { if (parent != null) { // This automagically unsets the internal parent parent.children.Remove(this); } if (value != null) { // This automagically sets the internal parent value.children.Add(this); } } } }
public ChildList<TreeItem<T>> Children { get { return children; } } }
public class Folder : TreeItem<Folder> { string name;
public Folder() { }
public string Name { get { return name; } set { name = value; } }
} }
"James Curran" <ja*********@mvps.org> wrote in message
news:ON**************@TK2MSFTNGP09.phx.gbl... um... HOw 'bout a nice simple:
parent.AddChild(child);
where AddChild is defined as
public AddChild(IChild pChild) { this.Children.Add(child); child.Parent = this; }
Because that relies on remember not to use .Children.Add :)
If I can do some extra work now, which reduces the number of bugs my
software might include, it's worth it! :)
Though I guess, returning Children as a ReadOnlyList (or whatever it's
called) and then having an Add method would work.. I don't think it's as
nice though :)
OK, plan 2 (A bit stripped down, but you should get the idea)
interface IParent
{
}
interface IChild
{
IParent Parent;
}
public class ChildList<T> : List<T>
{
private IParent oOwner;
public ChildList(IParent pOwner) : base()
{
oOwner = pOwner;
}
public new void Add(T item)
{
base.Add(item);
item.Parent = oOwner;
}
}
public class Folder : IParent, IChild
{
private IParent oParent;
prinvate ChildList<Folder> children;
public Folder()
{
children = ChildList<Folder>(this);
}
}
--
Truth,
James Curran
[erstwhile VC++ MVP]
Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
"Danny Tuppeny" <gr****@dannytuppeny.commmmmm> wrote in message
news:43***********************@ptn-nntp-reader03.plus.net... "James Curran" <ja*********@mvps.org> wrote in message news:ON**************@TK2MSFTNGP09.phx.gbl... um... HOw 'bout a nice simple:
parent.AddChild(child);
where AddChild is defined as
public AddChild(IChild pChild) { this.Children.Add(child); child.Parent = this; }
Because that relies on remember not to use .Children.Add :)
If I can do some extra work now, which reduces the number of bugs my software might include, it's worth it! :)
Though I guess, returning Children as a ReadOnlyList (or whatever it's called) and then having an Add method would work.. I don't think it's as nice though :)
"James Curran" <ja*********@mvps.org> wrote in message
news:%2****************@TK2MSFTNGP14.phx.gbl... OK, plan 2 (A bit stripped down, but you should get the idea)
<snip>
That's better - thanks :-) This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Volodymyr Sadovyy |
last post by:
Hi.
Can somebody refer me to resource with specified/analyzed/approximated
productivity in Java coding and Java code review tasks? Coding
productivity is more described in the net, but I didn't...
|
by: Arvie |
last post by:
I need some advice guys.. I am proposing that we get someone to do a
complete audit/review of our Java application codebase, about 1000
JSPs/Servlets and 100 EJBs. If I get firms to submit...
|
by: gs-code-review-bounces |
last post by:
Your mail to 'gs-code-review' with the subject
Re: Application
Is being held until the list moderator can review it for approval.
The reason it is being held:
Post by non-member to a...
|
by: andrew blah |
last post by:
Hello
I have recently released catchmail - a free (BSD license) open source
Python utility www.users.bigpond.net.au/mysite/catchmail.htm
This script processes in and outbound emails and stores...
|
by: Filippo |
last post by:
Hi,
In my organization we would like to activate a code review system, in
wich a developer have to pass a review from a reviewer before check in
the modified files in source safe. Is there any way...
|
by: Eigenvector |
last post by:
My question is more generic, but it involves what I consider ANSI standard C
and portability.
I happen to be a system admin for multiple platforms and as such a lot of
the applications that my...
|
by: JeanDean |
last post by:
I am looking for freeware tool which can review the c++ code(compiled
on g++).
Please share your experiences and details obout the usage of the tool.
|
by: Jo |
last post by:
Hi there:
I m wondering what can I do to improve my code, everytime I am coding
I feel like it could be done better. I started on c# a good months ago
and feel conformtable but sometimes I Need...
|
by: maxx233 |
last post by:
Hello all,
I'm new to OO design and have a question regarding where I should place some code. Here's a simplified situation:
I'm making an app to do create, submit, and track employee reviews...
|
by: corey |
last post by:
Secure Bytes audit and vulnerability assessment software Secure
Auditor named “Versatile tool” and earn “Five Star Ratings” in SC
Magazine Group Test
Secure Bytes is really pleased to share this...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
| |