I am implementing a tree think of it as a folder structure so I have a class that looks like:
public class Folder
{
//Various Props like Name etc.
public IList<Folder> Children{get;}
public Folder Parent {get;}
}
Now what I want is to be able to walk up and down the tree so given a root I can find a leaf, and given a leaf I can find the root node. So each child needs a parent. Now the question is what is the best way to add a new node to the tree. I have used two solutions in the past:
Add an AddChild(Folder) method to Folder which handles adding the folder, and can set the parent. The problem with this is I now have to lock my Children collection so you can't bypass this method.
Create my own Children collection which will be given a reference back to the instance, so it can handle setting the parent on the add. The problem with this I have to implement a new collection.
Use a collection which has events when items are added or deleted.
I am curious what patterns people generally use, and then if anyone has any suggestions for my specific use case. I am using nHibernate to persist my tree to SQL server. I'd rather not implement a custom collection as it's a lot of code to get this to work for something which is a very small part of my application.
After looking on MSDN you could try this:
List<Folder> children;
public ReadOnlyCollection<Folder> Children
{
get { return this.children.AsReadOnly(); }
}
If your private member must be declared as an IList then we can copy that into a list and then return it. But I really don't see a problem with using a concrete implementation as a private member. Changing the implementation later won't break compatibility.
IList<Folder> children;
public ReadOnlyCollection<Folder> Children
{
get
{
return new List<Folder>(this.children).AsReadOnly();
}
}
Go with number 1, but make your Children property IEnumerable so that users can't add to the collection.
Personally, I'd go with method 1. Allowing client code to manipulate the Children collection directly violates encapsulation in any case, so 'locking' the Children collection is the Right Thing™.
The 'proper' strategy for keeping your node relationships correct depends on the needs of your clients. I'm presuming that in this specific situation, you'd want clients to be able to alter the child nodes themselves, but not the Children collection. If that's the case, I think Rob Prouse's suggestion (make the Children property return an IEnumerable) is probably the best choice. In other situations, a ReadOnlyCollection would probably be better.
Implementing a custom collection's a lot of work; implementing a wrapper to an existing collection class that exposes only two or three methods isn't. And it seems like that's what you're looking for, judging from your response to JayArr. Something like:
public class ChildCollection
{
// _Children is maintained by the Folder class, hence the internal access specifier
internal Dictionary<KeyType, Folder> _Children = new Dictionary<KeyType, Folder>;
public this[KeyType key]
{
get
{
return _Children[key];
}
}
public IEnumerable<KeyType> Keys
{
get
{
return _Children.Keys;
}
}
}
I would go with option 1 and then make the Children property look like this:
public IEnumerable<Folder> Children
{
get { return this.children.GetEnumerator(); }
}
Now AddChild must be called to add the children. The collection is not accessible.
Related
I am trying to figure out a more elegant way to set the property of a parent in c#. I currently pass the parent into the child element, and reference it that way. This seems both cumbersome and possibly even incorrect.
The Child:
public class ValidatedField<T>
{
public OpenIssues parent { get; set; }
//Other values
public void Highlight()
{
parent.isNotValid = true;
isHighlighted = true;
}
}
And the Parent:
public class OpenIssues
{
public OpenIssues()
{
DateAppealFiled = new ValidatedField<DateTime?>(this);
}
public bool isNotValid { get; set; }
public ValidatedField<DateTime?> DateAppealFiled { get; set; }
}
Is there a more streamlined way to reference the parent in this case? Or am I doomed to sending the entire parent to the child, just to modify one value in the parent?
Is there a more streamlined way to reference the parent in this case?
Or am I doomed to sending the entire parent to the child, just to
modify one value in the parent?
The entire parent (in your words) is just a few bytes of reference/pointer
However,
You can essentially do this one of 3 ways
Pass in a concrete reference or interface from your parent.
Use events/delegate/action and register then trigger them on update
Or a decoupled pub/sub messaging system or mediator
What you are doing is fine, though all have their downsides and are cumbersome in different ways
The most modern approach is a decoupled messaging system, this is common in viewmodels where you don't want to couple view models and classes together. However, this is most likely overkill for trivial situations.
Also too, actions and events have their places as well. The parent(or someone) subscribes, and unsubscribes (well... should).
However, if you don't mind the tight coupling of your parent and child, and if there is little need to use them in different parent child configuration, just use references. No harm done.
Last day I ended up thinking about some collections interdependence.
I cannot put a better label, name, title, or whatever suggesting this situation... so feel free to suggest anything better than my cheap labeling, that is " Interdependent Collections Modifications Management".
Long story short, the example below.
First, let's consider a couple of classes:
public class DummyItem
{
public DummyItem(String name)
{
this.Name = name;
}
public String Name { get; set; }
}
// A kind of repository of DummyItems
public class BusinessClassProvider
{
public BusinessClassProvider()
{
this.Collection = new List<DummyItem>();
}
public IList<DummyItem> DummyItems{ get; private set; }
}
public class BusinessClassConsumer
{
public BusinessClassConsumer()
{
this.Collection = new Collection<DummyItem>();
}
public ICollection<DummyItem> DummItems{ get; private set; }
}
Now let's say that BusinessClassProvider.Collection is populated via some processes, user inputs, etc.
The BusinessClassConsumer Collection is something selected from BusinessClassProvider Collection by let's say also some user inputs or any other way.
Now if I remove or add a DummyItem from the BusinessClassProvider Collection I need to create Additional Nethods to wrap or eventually if they are some events supported to notify the others of what have been changed and remove accordingly the related other Collections (e.g. BusinessClassConsumer one) to also remove this item.
Basically it means a lot of boilerplate code and a lot of stuff to handle manually.
Of course, we could go with another strategy using IEnumerable as BusinessClassConsumer Collection but it does not provide the same options about indexing for instance, furthermore it forces to iterate over and over on BusinessClassProvider Collection.
I know it raises many more questions like which collection is kinda the provider and the others which consumes from.
Is there any frameworks via Attributes, or any other nasty tricks to enforce the dependency between several collections?
By the way, once again, is there anybody who knows how to label correctly this sort of situation?
If your need is to be notified when a collection change (item added, removed or the whole collection refreshed) you might want to use an ObservableCollection.
It's used mostly in WPF to notify the UI when a collection of item has changed and needs to be refreshed.
If your need is a producer/consumer collection, you might want to look for a BlockingCollection.
It's a thread safe collection that do all the producer/consumer things for you.
Yes, there are. Quite a few actually, but ObservableCollection that come with .net are not preferred. Instead one would use Rx-Linq(Reactive extension) that adds observables, Linq and schedulers together.
Does anyone know of a solid C# library / approach to manage a hierarchy/web type collection?
This would be a library that would basic consist of the concept of nodes & relationships, for example to model web pages/files linked under a URL, or modeling IT infrastructure. It would have key methods such as:
Node.GetDirectParents()
Node.GetRootParents()
Node.GetDirectChildren()
Node.GetAllChildren()
So it's smarts would include the ability to "walk the tree" of nodes based on the relationships when someone does ask for "give me all the children under this node" for example.
It ideally include a persistence layer, to save/retrieve such data to/from a databases (e.g. with a Nodes and Relationships table).
EDIT 1
Also note that it has to support the full open flexibility that there are nodes & relationships, and hence a node may be a child of more than one node. That is it can model more of a web map as opposed to a strict hierarchy.
Also then a Node may have more than one root/parent node (e.g. in the use case of modeling web page artefacts an image may be referenced on more than one web-site)
There are various samples on the web for how to create a directed graph (which is what you are actually looking for). For example http://www.jrcalzada.com/post/2010/02/14/Generic-Graph-Class-in-C.aspx
QuickGraph is the closest thing I've found so far...
http://quickgraph.codeplex.com/
SiteMapNode class?
http://msdn.microsoft.com/en-us/library/system.web.sitemapnode_properties(v=VS.100).aspx
The approach is easy, simply include a reference to an instance of self called 'Parent' and a collection of 'Children'. You can enforce this using the class constructor: require the Parent to be passed to the constructor and simply set Parent to that value and then add 'this' to the Children collection on the parent class.
e.g.
public class Whatever
{
public Whatever Parent {get; private set;}
protected List<Whatever> Children {get; private set;}
public Whatever(Whatever parent)
{
this.parent = parent;
this.Children = new List<Whatever>();
if (parent != null)
{
parent.Children.Add(this);
}
}
public IEnumerable<Whatever> AllChildren
{
return this.Children.Union(this.Children.SelectMany(child => child.AllChildren));
}
With this in place AllChildren, DirectChildren, Root are all easily implemented.
When you serialize to a database you only need to record the ParentID for each instance and can rebuild the tree after loading them all. The node with no parent is the root.
Is there a known pattern to inherit data in a hierarchical object structure? I have a hierarchical 'Item' structure which needs to inherit its 'Type' from its 'Parent' (have the same data as default). The type of sub item can be modified by its own, and when the type of parent Item changes, all sub items which their type is not changed, should get the new type of parent.
Note that I cannot fake it like
public string Type
{
get
{
if (type == null)
return Parent != null ? Parent.Type : null;
return type;
}
}
'cause I have to fill the values in the database, and the structure is too deep to use recursion and not worry about the performance.
The only way I can think of it now is
public string Type
{
set
{
type = value;
UpdateUnchangedChildren(value);
}
}
public int AddChild(Item item)
{
item.Type = Type;
return Items.Add(item);
}
Is there a better way?
Thanks.
It's a common problem, usually related to maintenance of various hierarchical settings/configurations. So, I guess a solution to it can be considered "a pattern".
Anyways, from the internal architecture perspective you have 2 major options:
normalized structure
denormalized structure
"Normazlied" is the one implemented with recursion. A particular piece of data is always stored in one place, all the other places have references to it (e.g., to parent). The structure is easily updated, but readng from it may be a problem.
"Denormalized" means that every node will store the whole set of settings for its level and whenever you update a node it takes some time to go down the hierarchy and corect all the children nodes. But the reading operation is instant.
And so the "denormalized" version seems to be more widely used, because the common scenario with settings is that you update them rarely, while read them often, hence you need better read performance. For example, Windows ACL security model uses the "denormalized" approach to make security checks fast. You can read how they resolve conflicts between the "inherited" and explicit permissions (ACEs) by checking them in a specific order. That might be an overkill for your particular system though, you can simply have a flag that a particular value was overriden or, on the opposite, reset to "default"...
Further details depend on your system needs, you might waht to have a "hybrid" architecture, where some of the fields would be "normalized" and some others won't. But you seem to be on the right way.
I'm not 100% sure what it is you are trying to do... but you could use generics to pass the type of a parent object into a child object... But having a setter there doesn't really make sense... The Parent object's type will be set when it's instantiated, so why would you have a setter there to change it.
Assuming you have something like this...
public class Child<T>
{
public string Type
{
get { return typeof(T).ToString(); }
}
}
So then, when you have a Parent Object of any type, you can pass that to your Child Property...
public class ParentA
{
public Child<ParentA> ChildObj { get; set; }
}
public class ParentB
{
public Child<ParentB> ChildObj { get; set; }
}
public class ParentC
{
public Child<ParentC> ChildObj { get; set; }
}
Calling any of those ChildObj.Type Properties will return ParentA, ParentB & ParentC respectively.
Buit I've a funny feeling you haven't fully explained what it is you're trying to do.
Can you post some more code examples showing a Parent Class & Child/Item Class
An obvious optimization would be to cache the value obtained from the parent when reading the type. That means you will only traverse each path at most once (whereas the naive solution means you'll be traversing each subpath again and again for each path containing it, which means up to O(h^2) instead of O(h)). That would work great if you have more reads than writes.
Consider this:
class Node
{
string _cachedParentType = null;
string _type;
string Type
{
get { return _type ?? _cachedParentType ?? (_cachedParentType = Parent.Type); }
set
{
_type = value;
foreach (var child in Children) { child._cachedParentType = null; }
}
}
}
This means with enough reads and few writes, reading becomes O(1) in the best case or, at worst, a "cache miss" will cost you O(h) with h being the height of the tree; while updating is O(k) with k being the branching level (because we only update one layer down!). I think this will generally be better than the UpdateUnchangedChildren solution (which I presume updates nodes recursively all the way to the leafs), unless you're doing WAY more reads than writes.
"...the structure is too deep to use recursion and not worry about the performance."
Have you actually measured this? How many items are you dealing with, how deep is the structure, and how common is it for items to not have their own "Type" value? What are your performance goals for the application, and how does the recursive solution compare with those goals?
It is very common for people to think that recursion is slow and therefore eliminate it from consideration without ever trying it. It is NEVER a good idea to reject the simplest design for performance reasons without measuring it first. Otherwise you go off and invent a more complicated solution when the simpler one would have worked just fine.
Of course, your second solution is also using recursion, just going down the hierarchy instead of up. If the child inserts are happening at a different time and can absorb the possible performance hit, then perhaps that will be more acceptable.
Previously, I had a class that wrapped an internal System.Collections.Generic.List<Item> (where Item is a class I created). The wrapper class provided several collection-level properties that provided totals, averages, and other computations on items in the list. I was creating a BindingSource around this wrapped List<> and another BindingSource around my class and was able to get at the Items in the wrapped list through the first BindingSource and the collection-level properties of the wrapper class using the second.
A simplified example looks like:
public class OldClass()
{
private List<Item> _Items;
public OldClass()
{
_Items = new List<Item>();
}
public List<Item> Items { get { return _Items; } }
// collection-level properties
public float AverageValue { get { return Average() } }
public float TotalValue { get { return Total() } }
// ... other properties like this
}
With the binding sources created in this way:
_itemsBindingSource = new BindingSource(oldClass.Items);
_summaryBindingSource = new BindingSource(oldClass);
Recently, I tried to change this class to be derived from System.Collections.Generic.List<Item> instead of keeping a wrapped List<> member. My hope was to get rid of the extra wrapper layer and use only one BindingSource instead of two. However, now I find that I cannot get at the properties that apply to all items in the list (such as AverageValue) when I do data binding. Only the properties of list items are available.
Am I forced to go back to using a wrapped List<> of Items? Or is there a way that I can get at both the properties of Items stored my new class as well as the properties that apply to the collection itself?
The system treats anything that implements IList (or IListSource) as a container, rather than an item. As such, you cannot bind to properties of anything that implements IList. As such, encapsulation (i.e. what you already have) is the best approach if you want to be able to bind to properties of the container.
However, you should note that many bindings support dot-notation in the source - i.e. either binding to "Items.SomeProperty", or setting the auxiliary property (typically DataMember) to specify sub-lists.
This allows you to have a single BindingSource, and have different controls bound to different levels in the hierarchy - i.e. you might have a TextBox bound to AverageValue, and a DataGridView (with the same DataSource) that has DataMember="Items".
The problem here is that you want to use your one class for two completely different purposes (in terms of bindings).
Example: The "AverageValue" property doesn't make sense to be on each item, because it's a global property that spans all items.
Either way, I'm guessing that your _itemsBindingSource is for a ComboBox or something, and that your _summaryBindingSource is for a PropertyGrid (or something like that).
What you could do, that might work in your situation (I can't be certain because I don't know what you are actually doing) is this:
1) Make your "OldClass" implement IEnumerable... and in that, simply return the enumeration from the list. That will give you the ability to bind to "oldClass" instead of "oldClass.Items".
2) Make the "public List Items" a field, instead of a property... or add the "Browsable(false)" attribute so it won't get bound to the PropertyGrid (this is a guess as it's unclear what you're using these bindings for).
Instead of creating a wrapper class around your List, have you considered creating an extension class (assuming you're using C# 3)
public static class MyExtensions
{
public static float GetAverage(this List<Item>)
{
// implementation
}
public static float GetTotal(this List<Item>)
{
// implementation
}
}
Of course, your properties become method calls (maybe C# 4 will fix this), but you would eliminate the wrapper entirely.