Any way to pass parent container objects single statement assignment? - c#

I was wondering if it is possible to pass a 'parent container' to an object initialization using single statement initialization? I am thinking about using this approach for hierarchical unit test variable assignments; thank you in advanced.
public class ParentObj
{
public IList<ChildObj> Children { get; set; }
}
public class ChildObj
{
private ParentObj Parent { get; set; }
public ChildObj(ParentObj parentObj) => Parent = parentObj;
}
class Program
{
static void Main(string[] args)
{
var parents = new List<ParentObj>();
var parent = new ParentObj();
parent.Children.Add(new ChildObj(parent));
parents.Add(parent);
// Anyway to duplicate the above with this style of initialization?
var moreParents = new List<ParentObj>
{
new ParentObj
{
Children = new List<ChildObj>
{
//new ChildObj( [need a reference to the parentObj] );
}
}
};
}
}

No, because at the time the Children are constructed your code doesn't have a reference to the parent. It's like C# is holding all the references for you, and doing all the linking, and just giving you the one end result (moreParents) object and you place it into the only thing you have a named reference for
You could change things like this:
public class ParentObj
{
private IList<ChildObj> _children;
public IList<ChildObj> Children {
get { return _children; }
set {
_children = value;
foreach (ChildObj c in value)
c.Parent = this;
}
}
}
public class ChildObj
{
public ParentObj Parent { get; set; }
}
So that the parent of the child can be set later, and then this code will work out:
var moreParents = new List<ParentObj>
{
new ParentObj
{
Children = new List<ChildObj>
{
new ChildObj(), new ChildObj()
}
}
};
Because you do have a way of referring to the parent (this)
Really, if you want to have some simple way of creating parents and children you need to create something that constructs them, so it can make a parent, and then then children supplying that parent.. Kinda like what you had in your first example!
ps; I'm not a fan of the "parent" and "child" terms of reference for this structure; they're normally used for inheritance hierarchies, where Child is-a Parent, rather than for container hierarchies where Parent has-a Children

Related

Call one method with parent class instead of two with childs

I have classes:
public class Throw
{
public double speed { get; set; }
public double accurency { get; set; }
}
public class FastThrow : Throw{}
public class LowThrow : Throw{}
Instead of having:
public static FastThrow SetFastThrow(List<object> args)
{
return new FastThrow
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
public static LowThrow SetLowThrow(List<object> args)
{
return new LowThrow
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
I want to have one with parent class:
public static Throw SetThrow(List<object> args)
{
return new Throw
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
To declare list or some other generic interface with child class with instance of parent class. Then adding new elements to existing collection. I know that below example has compilation errors, but it should look like:
List<List<object>> firstList = new List<List<object>>();
public void Main()
{
IList<FastThrow> secondList = new List<Throw>();
foreach (var item in firstList)
{
secondList.Add(SetThrow(item));
}
}
I read about contravariance and do not know if this is possible.
You can't. Rahter than
To declare list or some other generic interface with child class with
instance of parent class.
you should
To declare list or some other generic interface with parent class with
instance of chidlren class.
The second way, as Anirban said, use generic classes, refactor your SetThrow method as following:
public static T SetThrow<T>(List<object> args) where T : Throw, new()
{
return new T
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
So that you can use SetThrow method only to generate different kinds of classes as long as they are child classes. e.g:
IList<FastThrow> secondList = new List<FastThrow>();
foreach (var item in firstList)
{
secondList.Add(SetThrow<FastThrow>(item));
}
And generic classes are strong typed and elegant to use.

Method of a generic class doesn't see 'new' property of a child class

I have a generic tree node class ObservableTreeNode<K,V>, with a method that should go through all nodes of a tree and examine them. I have two more classes:
ElementTreeNode : ObservableTreeNode<string, HierarchyElement>, and
ElementTreeNodeVisual : ElementTreeNode.
The generic class looks like this:
public class ObservableTreeNode<K, V>
{
public K Key { get; set; }
public V Value { get; set; }
public ObservableCollection<ObservableTreeNode<K, V>> Children { get; set; }
public ObservableTreeNode()
{
this.Children = new ObservableCollection<ObservableTreeNode<K, V>>();
}
public static IEnumerable<T> FindNodeInTree<T>(
T rootNode, Func<T, bool> predicate, bool firstOnly = false
) where T : ObservableTreeNode<K, V>
{
var resultNodes = new List<T>();
var nodeQueue = new Queue<T>();
nodeQueue.Enqueue(rootNode);
while (nodeQueue.Any())
{
T currentNode = nodeQueue.Dequeue();
Debug.WriteLine("Current node key: {0}", currentNode.Key);
if (predicate(currentNode))
{
Debug.WriteLine("Match!");
resultNodes.Add(currentNode);
if (firstOnly)
{
Debug.WriteLine("-FindInContext");
return resultNodes;
}
}
Debug.WriteLine("The current node has {0} children.", currentNode.Children.Count);
foreach (T n in currentNode.Children)
{
Debug.WriteLine("Enqueue child...");
nodeQueue.Enqueue(n);
}
}
return resultNodes;
}
}
In my ElementTreeNodeVisual class, I must hide the Children property with a new one, otherwise the 3rd party (Infragistics' XamDataTree) control in my WPF application wouldn't enumerate the child nodes. So my ElementTreeNodeVisual class looks like this:
public class ElementTreeNodeVisual : ElementTreeNode
{
public bool IsExpanded { get; set; }
public bool IsSelected { get; set; }
public new ObservableCollection<ElementTreeNodeVisual> Children
{
get;
set;
}
public ElementTreeNodeVisual(ElementTreeNode elementTreeNode)
{
this.Children = new ObservableCollection<ElementTreeNodeVisual>();
this.Element = elementTreeNode.Element;
this.Parent = elementTreeNode.Parent;
foreach (ElementTreeNode child in elementTreeNode.Children)
{
this.Children.Add(new ElementTreeNodeVisual(child));
}
}
}
}
My problem is, when I try call the ElementTreeNodeVisual.FindNodeInTree method, the method seems to be seeing the Children property of the base class - which has no items.
This is how I call the method:
Func<ElementTreeNodeVisual, bool> isExpandedFunc = delegate(ElementTreeNodeVisual node) { return node.IsExpanded; };
foreach (ElementTreeNodeVisual node in _hierarchyNodeVisuals)
{
var expandedNodes = ElementTreeNodeVisual.FindNodeInTree<ElementTreeNodeVisual>(node, isExpandedFunc);
foreach (ElementTreeNode expandedNode in expandedNodes)
{
expandedNodeIds.Add(expandedNode.Key);
}
}
If I set a watch on the node variable inside the foreach loop, it shows the new Children property, with several child nodes. The Debug.WriteLine(...) in the FindNodeInTree method however, says there are 0 children.
As an emergency solution, I've copy-pasted the FindNodeInTree method and changed the T parameter to where T : ElementTreeNodeVisual. It works like this, but in the end there shouldn't be any copy-pasted code in there...
What should I change (either in the generic class or the child class) to make the FindNodeInTree method see the new property, when it's called on the child class?
Well, It's a little strange method but it should work.
First, add a virtual property collection in your base class. For example:
public virtual ObservableCollection<ObservableTreeNode<K, V>> VirtualChildren {
get { return Children; }
}
In your searching method change Children to VirtualChildren:
public static IEnumerable<T> FindNodeInTree<T>(
T rootNode, Func<T, bool> predicate, bool firstOnly = false
) where T : ObservableTreeNode<K, V>
{
var resultNodes = new List<T>();
var nodeQueue = new Queue<T>();
nodeQueue.Enqueue(rootNode);
while (nodeQueue.Any())
{
T currentNode = nodeQueue.Dequeue();
Debug.WriteLine("Current node key: {0}", currentNode.Key);
if (predicate(currentNode))
{
Debug.WriteLine("Match!");
resultNodes.Add(currentNode);
if (firstOnly)
{
Debug.WriteLine("-FindInContext");
return resultNodes;
}
}
Debug.WriteLine("The current node has {0} children.", currentNode.VirtualChildren.Count);
foreach (T n in currentNode.VirtualChildren)
{
Debug.WriteLine("Enqueue child...");
nodeQueue.Enqueue(n);
}
}
return resultNodes;
}
And override VirtualChildren property in ElementTreeNodeVisual:
public override ObservableCollection<ObservableTreeNode<string, HierarchyElement>> VirtualChildren
{
get { return new ObservableCollection<ObservableTreeNode<string, HierarchyElement>>(Children); }
}
Of course, returning new collection in property each time isn't very good. So you may replace this property by the virtual method or subscribe on CollectionChanged event Children property in ElementTreeNodeVisual class and add new elements to your inner collection in a real time, for instance.

How To Form my Node and Tree Generic Classes

I have an IList<Category>
The Category type is coming from my Category Table in SQL Server:
Table: Category
CategoryID, ParentCategoryID
so typical heirarchy in one table.
So if I have this IList of Categories that contain the node relationships, then I am trying to figure out how this fits into making a Node and Tree like a lot of people are doing. And how would the constructor look and this class be created in terms of usage?
I think it makes sense here to create a generic Node class and Tree class so I can reuse in the future I think for other tree types.
So if I have something like this, how is T being used and what am I benefiting from?
(pseudo code here)
public class Node<T>
...
Node<T> _parentNode;
List<Node<T>> _children;
private void SetParentNode(T)
private void AddChild(T)
... etc.
trying to understand the concept here on why a Generic Node class would be used for any type coming in like Childeren, etc. that contains a child/parent relationship (int Ids)
UPDATE
So having an issue here with the GroupBy recommendation. Check out what I tried to do with your example:
First I have this property in my Tree class:
public Dictionary, IList>> ParentNodeAndRelatedChildrenFlattenedMap { get; private set; }
and incoming to my class's constructor is a IList dependencies that I converted (looped and created a new Node for every one of them) to a IList>
Now I'm trying to group that list by Node.ParentId as you were talking so that I get a grouping on Parent Nodes and since each node has its children property it's easy to find out what the related children are to those parent nodes.
But here is the problem now later down in my code:
public void CreateFlattenedMap()
{
var parentGroups = _nodeDependencies.GroupBy(d => d.ParentNodeId);
var dictionary = parentGroups.ToDictionary(d => d, d => d.ToList());
ParentNodeAndRelatedChildrenFlattenedMap = dictionary;
}
well it's not liking my assignment of dictionary because it's an > dictionary that's created by the ToDictionary(). So not sure how to get this grouping grouped and to a dictionary that is a , List> where Node in the dictionary is the Node instance for that parent I'm grouping on (yea I'm grouping on its Node.ParentId but I want the Node though in the ToDictionary in the end) and the List> is the list of Children Nodes from the Parent Node.Children property.
This is what a more complete implementation would look like:
public class TreeNode<T>
{
private T _item;
private TreeNode<T> _parentNode;
private List<TreeNode<T>> _children;
public TreeNode(T item)
{
_item = item;
}
public void SetParentNode(T parent)
{
_parentNode.Item = parent;
}
public T Item
{
get { return _item; }
set { _item = value; }
}
public void AddChild(T child)
{
_children.Add(new TreeNode<T>(child));
}
public void RemoveChild(T child)
{
var node = _children.FirstOrDefault(e => e.Item.Equals(child));
if (node != null)
_children.Remove(node);
}
}
And your questions:
How would the constructor look and this class be created in terms of usage?
As you can see from the above in AddChild(), simply specify the type of the child for the constructor.
var node = new TreeNode<T>(item);
So if I have something like this, how is T being used and what am I benefiting from?
The use of generics can same a lot of time rewriting code when done right. In the implementation above, we can make a tree structure out of basically any type we want by simply changing T. So this saves us a lot of time if we need a tree structure for more than one type.
var intTreeNode = new TreeNode<int>(10);
var stringTreeNode = new TreeNode<string>("hello world");
Generically really take some exposure time before it clicks and you "just get it", keep at it.
Constructing the tree
To construct the tree from a list of categories that may or may not have parent categories you will need to iterate through the list in some way. A decent way to go about this would be to first organise them into groupings based on the ParentCategoryID and constructing the tree. Something like this (untested):
public List<TreeNode<Category>> ConstructCategories(List<Category> categories)
{
var groups = categories.GroupBy(e => e.ParentCategoryID);
var rootGroup = groups.Single(e => e.Key == null);
var categories = List<TreeNode<Category>>();
foreach (var category in rootGroup)
{
// Create and fill category
var node = new TreeNode<Category>(category);
ConstructChildrenCategories(node, groups);
categories.Add(node);
}
}
public void ConstructChildrenCategories(TreeNode<Category> node, IEnumerable<IGrouping<Category>> groups)
{
var group = groups.Single(e => e.Key == node.Item.CategoryID);
foreach (var category in group)
{
// Create and fill category
var childNode = new TreeNode<Category>(category);
ConstructChildrenCategories(childNode, groups);
// We could do this automatically in both methods.
childNode.SetParent(node.Item);
node.AddChild(childNode);
}
}
This may be helpful:
public interface ICategory
{
int Id { get; }
int ParentId { get; }
}
public class Category : ICategory
{
int id;
int parentId;
public int Id { get { return id; }}
public int ParentId { get { return parentId; }}
}
And this is the Node class:
public class Node<T> where T : ICategory
{
Node<T> _parentNode;
List<Node<T>> _children;
public Node<T> Parent { get { return _parentNode; }}
public Node<T> Child(int index) { return _children[index]; }
public T Value;
public Node(T value)
{
this.Value = value;
}
public void AddChild(T item)
{
Node<T> child = new Node<T>(item);
this._children.Add(child);
child._parentNode = this;
}
}
And this is the Tree class:
public class Tree<T> where T : ICategory
{
List<Node<T>> values;
public Tree()
{
this.values = new List<Node<T>>();
}
public Node<T> FindNode(int id)
{
if (values.Exists(input => input.Value.Id == id))
{
return values.Find(input => input.Value.Id == id);
}
else { return null; }
}
public void AddNode(T value)
{
Node<T> parent = FindNode(value.ParentId);
if (parent != null)
{
parent.AddChild(value);
}
}
}
You can't make all the function of tree and treenode.
rather add the class data to Treenode.
for example
class MyClass
{
public int A;
public string B;
}
...
TreeNode Node = TreeView.Nodes.Add("AAA");
MyClass Data = new MyClass();
Node.Tag = Data;
The Data assigned to TreeNode will not be deleted. and you can use whole tree property and Nodes member, too.
the only thing that you should do is typecast when use data of the node.
TreeNode Node = TreeView.Nodes[0];
MyClass Temp = Node.Tag as MyClass;

C# change type of child class in parent(abstract) class

Code:
abstract class Parent{
void changeChild(){
}
}
class Child1: Parent{
}
class Child2: Parent{
}
//-----
Parent parent = new Child1(); //instantiated as Child1
parent.changeChild(); //change type of this class to Child2
so parent should be instance of Child2 class.
I understand that Child1 can be different from Child2(more/less fields, methods),
but I just want to call constructor on this object, which is not allowed.
simple
parent = new Child2();
could be done, but there is like 10 child classes(Growing) and I want to move this into parent class
Is this somehow possible in c#?
Thanks
You can't change the type of an existing object, but you can create a new object and return it.
Example:
abstract class Parent{
Parent ChangeChild<T>() where T : Parent {
if (typeof(T) == typeof(Child1)) {
return new Child1(this);
if (typeof(T) == typeof(Child2)) {
return new Child2(this);
} else {
throw new NotImplementedException("Unhandled type");
}
}
}
class Child1: Parent{
public Child1() {} // create
public Child1(Parent source) {} // convert
}
class Child2: Parent{
public Child2() {} // create
public Child2(Parent source) {} // convert
}
Parent parent = new Child1();
parent = parent.ChangeChild<Child2>();
Automapper might be your best bet.
T changeChild<T>() : Parent{
// change the type here.
}
Would something like this work?
abstract class Parent {
private Parent Proxy;
public void ChangeChild<T>() where T : Parent, new() {
Proxy = new T();
}
}
You'd have to use the Proxy object to call members and properties.
Well, if you want just that ctor is called automaticcally, should be enough to wtrite something, like
class Child1: Child2{
}
class Child2: Parent{
}
So you have Child2 ctor that will be called when Child1 is constructed. But it's completely different architecture design in regard if yours.
If it's not somethign you're asking for, please clarify.
If you need to change type of some object in runtime, it's not case for inheritance. You should use composition here. Try something like Strategy (if Parent class represents some behavior).
public class Foo
{
// provide default value (or inject it via ctor)
private Parent _parent = new Child1();
public void ChangeChild(Parent parent){
_parent = parent;
}
public void Bar()
{
_parent.DoSomething();
}
}
public abstract class Parent
{
public abstract void DoSomething();
}
public class Child1: Parent
{
public override void DoSomething() { ... }
}
public class Child2: Parent
{
public override void DoSomething() { ... }
}
And now you can change type of dependency at runtime:
Foo foo = new Foo(new Child1());
foo.Bar(); // child1 implementation used
foo.ChangeChild(new Child2());
foo.Bar(); // child2 implementation used
You cannot do it like this. Perhaps you could create Parent as a wrapper class
class Parent
{
Parent _child;
public Parent(Parent child)
{
_child = child;
}
public void ChangeChild(Parent child)
{
_child = child;
}
public string AProperty {
get { return _child.AProperty; }
set { _child.AProperty = value; }
}
public int AMethod(int x)
{
return _child.AMethod(x);
}
}
And then
Parent parent = new Parent(new Child1());
parent.AProperty = "hello";
int y = parent.AMethod(55);
parent.ChangeChild(new Child2());
Note: The parent should not have knowledge about the specific children in a good OO-design. This ensures that you can create new children later (say Child3) without having to change Parent.
However, if this is not an issue for you and you want the parent to care automatically about changing children then change or overload the constructor with
public Parent()
{
_child = new Child1();
}
and change or overload ChangeChild with
public void ChangeChild()
{
if (_child is Child1) {
_child = new Child2();
} else {
_child = new Child1();
}
}

Property is user defined?

How can I now in a list obtained with Type.GetProperties() if the properties are user-defined?
For example
class test
{
public string propertyOne{get;set;}
public string propertyTwo{get;set;}
}
With typeof(test).GetProperties() I get two PropertyInfo, how can I now they are user defined?
Information about the context, here is the test that should pass
[Test]
public void GetFullNameScalarPropertiesTest()
{
// Act
var properties = ReflectionHelper.GetFullNameScalarProperties(typeof(Parent));
// Assert
Assert.True(properties.Contains("PropertyOne"));
Assert.True(properties.Contains("Child.PropertyTwo"));
Assert.True(properties.Contains("Child.GrandChild.PropertyThree"));
Assert.That(properties.Count, Is.EqualTo(3));
}
class Parent
{
public Parent()
{
Child = new Child();
}
public string PropertyOne { get; set; }
public Child Child { get; set; }
}
class Child
{
public Child()
{
GrandChild = new GrandChild();
}
public string PropertyTwo { get; set; }
public GrandChild GrandChild { get; set; }
}
class GrandChild
{
public string PropertyThree { get; set; }
}
So, in a recursive method I'm getting properties and creating a list with the names
ATM the code that pass this test is
public static IList<string> GetFullNameScalarProperties(Type type)
{
var lista = new List<string>();
var path = string.Empty;
var properties = type.GetProperties();
foreach (var propertyInfo in properties)
GetFullNameScalarProperties(propertyInfo, path, lista);
return lista;
}
private static void GetFullNameScalarProperties(PropertyInfo propertyInfo, string path, ICollection<string> lista)
{
if (!string.IsNullOrEmpty(path))
path += ".";
path += propertyInfo.Name;
if (propertyInfo.PropertyType.FullName != null)
if (propertyInfo.PropertyType.FullName.StartsWith("System"))
{
lista.Add(path);
return;
}
var properties = propertyInfo.PropertyType.GetProperties();
foreach (var pi in properties)
GetFullNameScalarProperties(pi, path, lista);
}
It's unclear what you mean by "user-defined" - are you trying to spot the difference between an automatically implemented property and one which has been written by hand? If so, an automatically implemented property will have the [CompilerGenerated] attribute on the getter and the setter.
using System;
using System.Runtime.CompilerServices;
class Program
{
public int AutomaticallyImplemented { get; set; }
public int HandWritten {
get { return 0; }
set {}
}
static void Main()
{
foreach (var property in typeof(Program).GetProperties())
{
bool auto = property.GetGetMethod().IsDefined
(typeof(CompilerGeneratedAttribute), false);
Console.WriteLine("{0}: {1}", property.Name, auto);
}
}
}
Obviously you'd normally want to check whether there is a getter first :)
If you want to get those non-inherited members, try Type.GetProperties, and pass BindingFlags.DeclaredOnly as an argument like:
var properties = typeof(test).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
Maybe you want to know which one aren't .NET Framework ones.
You can invoke Type.GetProperties and iterate found properties with LINQ in order to know where these were defined in your class, and which ones, in framework level.
As others said, you need PropertyInfo.DeclaringType to know where some property was defined.
If any of your project's object are inheriting from some base class, maybe you can do this:
someObject.GetType().GetProperties().Where(propInfo => propInfo.DeclaringType.IsSubclassOf(typeof(ProjectBaseType))
There is nothing like a 'user defined' property. To learn in what type in an inheritance hierarchy a property was declared, have a look at PropertyInfo.DeclaringType.
If you want to findout whether or not a property is inherited compare the PropertyInfo.DeclaringType to the Type you are testing

Categories