After looking at major pattern designs, I can't seem to make up my mind around the best to one to decouple classes in a big hierarchy system, specially were it concerns on avoiding injecting a Parent property in EVERY object along the way.
Some of the premises are:
A child might me removed from one parent and added to another.
Somewhere down the hierarchy, I need to access Parent of type X.
As mentioned before, I would like to avoid injecting a Parent (either by property or constructor) to it's children.
I have 1..1 and 1...N cardinalities.
The hierarchy from root to furthest leaf is quite extent.
If it was a small project, I would be fine with this (pseudo code):
public abstract class BaseObject()
{
public BaseObject Parent { get; set; }
}
public class RootObject() : BaseObject
{
public int Id { get; }
public ParentObject[] Parent { get; set; }
}
public class ParentObject() : BaseObject
{
public int Id { get; }
public ChildObject[] Parent { get; set; }
}
public class ChildObject() : BaseObject
{
public int Id { get; }
public void DoSomething()
{
//...navigate through Parent to get RootObject (or any other type in between that I might need)...
}
}
Can anyone point me out to the right direction?
All these requirements remind me graph data structure:
A child might me removed from one parent and added to another.
Somewhere down the hierarchy, I need to access Parent of type X.
As mentioned before, I would like to avoid injecting a Parent (either by property or constructor) to it's children.
I have 1..1 and 1...N cardinalities.
The hierarchy from root to furthest leaf is quite extent.
The easiest storage would be List<Node> where each node contains links to its predecessors and successors:
class Example
{
public List<Node> InitGraph()
{
var nodes = new Dictionary<string, Node>();
nodes.Add("Head", new Node("Head"));
nodes.Add("T1", new Node("T1"));
nodes.Add("T2", new Node("T2"));
// While that works, a method is nicer:
nodes.Add("C1");
// These two lines should really be factored out to a single method call
nodes["Head"].Successors.Add(nodes["T1"]);
nodes["T1"].Predecessors.Add(nodes["Head"]);
nodes["Head"].Successors.Add(nodes["T2"]);
nodes["T2"].Predecessors.Add(nodes["Head"]);
// Yes. Much nicer
nodes.Connect("Head", "C1");
nodes.Connect("T1", "C1");
nodes.Connect("T2", "C1");
var nodelist = new List<Node>(nodes.Values);
return nodelist;
}
}
and NodeHelper class:
public static class NodeHelper
{
public static void Add(this Dictionary<string, Node> dict, string nodename)
{
dict.Add(nodename, new Node(nodename));
}
public static void Connect(this Dictionary<string, Node> dict, string from, string to)
{
dict[ from ].Successors.Add(dict[ to ]);
dict[ to ].Predecessors.Add(dict[ from ]);
}
}
and Node class:
public class Node
{
public string Name { get; set; }
public int Coolness { get; set; }
public List<Node> Predecessors { get; set; }
public List<Node> Successors { get; set; }
public Node()
{
Coolness = 1;
}
public Node(string name) : this()
{
this.Name = name;
}
}
Related
I've a class with Tree hierarchy as below. I need to set Leaf node to status "InProgress". Then All ancestors needs to have change from NotStarted to InProgress. And if all leaf nodes were Complete, it immediate parent status need to be Complete. Is there a quick way to do it other than recursively iterating multiple times?
pubic class Node
{
public string Name { get; set; }
public List<Node> Children { get; set; } = new List<Node>();
public int NodeStatus {get; set;} // 1=>NotStarted (default); 2=> InProgress; 3=>Complete
}
One simple way can be that you make a different class for child notes and notify your parent class each time when its property is changed:
Parent
public class Node
{
public string Name { get; set; }
public List<Node> Children { get; set; } = new List<Node>();
private int _nodeStatus;
// 1=>NotStarted (default); 2=> InProgress; 3=>Complete
public virtual int NodeStatus
{
get => _nodeStatus;
set
{
_nodeStatus = value;
// If started, then change all children property to 'In progress'
if(value == 2)
Children.ForEach(child => child.NodeStatus = 2);
}
}
private int CountCompleted { get; set; }
public void NotifyChildChanged(int childStatus)
{
if (childStatus == 3)
{
CountCompleted++;
if(CountCompleted == Children.Count)
// Do your stuff
}
else
{
CountCompleted--;
}
}
}
Child
public class ChildNode : Node
{
private int _nodeStatus;
public override int NodeStatus
{
get => _nodeStatus;
set
{
_nodeStatus = value;
NotifyChildChanged(value);
}
}
}
Basically, what you will have is a separate implementation of NodeStatus for Parent and Child classes and inside of their implementation you just put other needed methods like changing childs' values or notifying parent about child's complete. In the parent's case, however, you should be careful, because every time you change the parent it will change all children, so you might want to have also some kind of private bool which will be checking whether the progress has already been started or not.
P.S for simplicity, I used just methods, however, you might want to implement it through delegates and events.
I´m having a hard time trying to understand how Ninject´s NamedScope module should work. In my mind, each (defined)scope should be used to contextualize bindings that are "InNamedScope".
With this toy example:
void Main()
{
var kernel = new StandardKernel(new NamedScopeModule(), new ContextPreservationModule());
kernel.Bind<ParentC>().ToSelf().WithConstructorArgument("name", "Name1").DefinesNamedScope("scope1");
kernel.Bind<Intf>().ToConstant(new MyC() { ID = 1} ).InNamedScope("scope1");
kernel.Bind<ParentC>().ToSelf().WithConstructorArgument("name", "Name2").DefinesNamedScope("scope2");
kernel.Bind<Intf>().ToConstant(new MyC() { ID = 2 }).InNamedScope("scope2");
kernel.GetAll<ParentC>().Dump();
}
public class Intf
{
int ID { get; set; }
}
public class MyC : Intf
{
public int ID { get; set; }
}
public class ParentC
{
public ParentC(Intf[] c, string name)
{
this.C = c;
Name = name;
}
public string Name { get; set; }
public Intf[] C { get; set; }
}
for me, should yield something like this:
But instead, I get an exeception:
UnknownScopeException: Error activating UserQuery+Intf
The scope scope2 is not known in the current context.
what am I missing ?
In Ninject, scope is related to lifetime of objects. I see named scope more as a way of injecting the same instance into different classes, like this:
public class Parent {
public Parent(Child child, GrandChild grandChild) {}
}
public class Child {
public Child(GrandChild grandchild) {}
}
public class GrandChild {}
kernel.Bind<Parent>().ToSelf().DefinesNamedScope("scope");
kernel.Bind<GrandChild>().ToSelf().InNamedScope("scope");
kernel.Get<Parent>();
The grandChild injected into Parent is the same instance as is injected into Child.
public class ParentClass
{
public int myId;
public string commonField1;
public string commonField2;
public string commonField3;
public string changeable;
public List<ChildClass> children;
public ParentClass(int id)
{
myId = myId;
}
public createChildren()
{
for(int i = 0; i < 999999; i++)
{
children.Add(new ChildClass(id));
}
}
}
public class ChildClass : ParentClass
{
public ChildClass(int id) : base (id)
{
myId = myId;
changeable = "new";
}
}
Because ChildClass only exists in the context of it's ParentClass, and there will be 999999 children. That is creating 999999 copies of all the commonField's when in reality it just needs a reference to it's parent. The only real thing a ChildClass needs to store besides references is changeable.
How can this be accomplished?
I am almost thinking a better approach when I need the children is just to make 999999 shallow copies of the ParentClass and just change the 999999 changeable fields. Shallow copies will have references to commonField1 or would it deep copy values?
You have one thing right, thats a lot of repeated data if commonFieldX is truly unchanging.
I see several solutions:
Prefer Composition over Inheritance
Why are you inheriting at all? If there is no polymorphic behavior, then just pass the base class instance to the 10000 children and call it good:
public createChildren()
{
for(int i = 0; i < 999999; i++) {
children.Add(new ChildClass(id, this));
}
}
public class ChildClass
{
public ChildClass(int id, ParentClass parent) : base (id)
{
myId = myId; //This shouldn't be part of the base class?
changeable = "new"; //Same here
myParent = parent;
}
}
Share those variables among all instances
static members belong to the "global" instance, so they won't be recreated for each derived object:
public class ParentClass
{
public int MyId {get; set;}
public static string CommonField1 {get; set;}
public static string CommonField2 {get; set;}
public static string CommonField3 {get; set;}
public string Changeable {get; set;}
Note that some of this should likely be protected instead of public and you should always expose public fields via properties instead of directly. Of course, if you have multiple instances of ParentClass that have differing values of those fields, this is a no-go.
If child and parent should have some relation (i.e. common parent class to share methods/properties), but child need to share properties with parent you can redirect properties request to parent (note that it would men getting property of deeply nested child is very slow):
public class Node
{
public virtual string Field {get {return parent != null ? parent.Field : field;}}
public Node parent;
public List<Node> children;
public Node()
{
children = new List<Node>();
}
public createChildren()
{
for(int i = 0; i < 999999; i++)
{
children.Add(new ChildNode(i, this));
}
}
}
public class ChildNode : Node
{
public override string Field {get {return parent.Field;}}
public ChildNode(Node parent)
{
this.parent = parent;
}
}
public class RootNode : Node
{
public override string Field {get {return "Root";}}
public RootNode()
{
this.parent = null;
}
}
I have a viewmodel that needs to display a certain IEnumerable field as semicolon-separated textbox. At first I thought of using DefaultModelBinder to transform it, but I had trouble thinking how to achieve it in both directions (dto <-> viewmodel).
Nicknames is the field I'm trying to display as one textbox separated by semicolon.
public class Parent
{
public IEnumerable<Child> Children { get; set; }
}
public class Child
{
public IEnumerable<string> Nicknames { get; set; }
}
So I decided to try AutoMapper, I created two ViewModels:
public class ParentViewModel
{
public IEnumerable<ChildViewModel> Children { get; set; }
}
public class ChildViewModel
{
public string Nicknames { get; set; }
}
Then, I created mappings, like this for the children (omitted the other-way conversion for brevity)
Mapper.CreateMap<Child, ChildViewModel>().ForMember(
d => d.Nicknames, o => o.ResolveUsing<ListToStringConverter>().FromMember(s => s.Nicknames);
Then, for the parent, created a naive map (again, omitted the other-way)
Mapper.CreateMap<Parent, ParentViewModel>();
I truly expected the child mappings occur automatically, but they don't, I've already created too much "proper" code to solve a really simple problem which in any other simpler/older non-MVC environment, I'd be done with a long time ago :) How can I proceed and tell AutoMapper to transform the children without writing another "children member resolver".
Have I overthought this and there's a simpler way?
Thank you!
try
Mapper.CreateMap<Parent, ParentViewModel>();
Mapper.CreateMap<Child, ChildViewModel>();
var v = Mapper.Map<Parent, ParentViewModel>(parent);
Found this solution https://stackoverflow.com/a/7555977/1586498, that works for me:
Mapper.CreateMap<ParentDto, Parent>()
.ForMember(m => m.Children, o => o.Ignore()) // To avoid automapping attempt
.AfterMap((p,o) => { o.Children = ToISet<ChildDto, Child>(p.Children); });
The ToISet function is defined in the above link.
Simpler examples 'just work' in LinqPad - so more investigation is required.
A complete listing of a working program:
public class Child{ public string Name {get; set; }}
public class ChildDto{ public string NickName {get; set; }}
public class Parent{ public virtual IEnumerable<Child> Children {get; set; }}
public class ParentDto{ public IEnumerable<ChildDto> Kids {get; set; }}
private static void Main()
{
AutoMapper.Mapper.CreateMap<Parent, ParentDto>().ForMember(d=>d.Kids, opt=>opt.MapFrom(src=>src.Children));
AutoMapper.Mapper.CreateMap<Child, ChildDto>().ForMember(d=>d.NickName, opt=>opt.MapFrom(src=>src.Name));
var pList = new HashSet<Parent>{
new Parent{ Children = new HashSet<Child>{new Child{Name="1"}, new Child{Name="2"}}},
new Parent{ Children = new HashSet<Child>{new Child{Name="3"}, new Child{Name="4"}}},
};
var parentVm = AutoMapper.Mapper.Map<IEnumerable<Parent>, IEnumerable<ParentDto>>(pList);
parentVm.Dump();
}
I have a customer hierarchy like so:
abstract class Customer {
public virtual string Name { get; set; }
}
class HighValueCustomer : Customer {
public virtual int MaxSpending { get; set; }
}
class SpecialCustomer : Customer {
public virtual string Award { get; set; }
}
When I retrieve a Customer, I would like to show on the web form the properties to edit/modify. Currently, I use if statements to find the child customer type and show the specialized properties. Is there a design pattern (visitor?) or better way so I can avoid the "if" statements in presentation layer? How do you do it?
Further information: This is an asp.net website with nHibernate backend. Each customer type has its own user control on the page that I would like to load automatically given the customer type.
Can you use reflection to get the list of properties specific to an subclass (instance)? (Less error-prone.)
If not, create a (virtual) method which returns the special properties. (More error prone!)
For an example of the latter:
abstract class Customer {
public virtual string Name { get; set; }
public virtual IDictionary<string, object> GetProperties()
{
var ret = new Dictionary<string, object>();
ret["Name"] = Name;
return ret;
}
}
class HighValueCustomer : Customer {
public virtual int MaxSpending { get; set; }
public override IDictionary<string, object> GetProperties()
{
var ret = base.GetProperties();
ret["Max spending"] = MaxSpending;
return ret;
}
}
class SpecialCustomer : Customer {
public virtual string Award { get; set; }
public override IDictionary<string, object> GetProperties()
{
var ret = base.GetProperties();
ret["Award"] = Award;
return ret;
}
}
You probably want to create sections (fieldsets?) on your Web page, anyway, so if would come into play there, making this extra coding kinda annoying and useless.
I think a cleaner organization would be to have a parallel hierarchy of display controls or formats. Maybe use something like the Abstract Factory Pattern to create both the instance of Customer and of CustomerForm at the same time. Display the returned CustomerForm instance, which would know about the extra properties and how to display and edit them.
new:
interface CustomerEdit
{
void Display();
}
edit:
abstract class Customer {
protected CustomerEdit customerEdit; // customers have an object which allows for edit
public virtual string Name { get; set; }
public void Display() { customerEdit.Display(); } // allow the CustomerEdit implementor to display the UI elements
}
// Set customerEdit in constructor, tie with "this"
class HighValueCustomer : Customer {
public virtual int MaxSpending { get; set; }
}
// Set customerEdit in constructor, tie with "this"
class SpecialCustomer : Customer {
public virtual string Award { get; set; }
}
usage:
Customer whichCouldItBe = GetSomeCustomer();
whichCouldItBe.Display(); // shows UI depeneding on the concrete type
Have you tried something like this:
public class Customer<T>
where T : Customer<T>
{
private T subClass;
public IDictionary<string, object> GetProperties()
{
return subClass.GetProperties();
}
}
With a subclass of:
public class FinancialCustomer : Customer<FinancialCustomer>
{
}
This is off the top of my head so might not work. I've seen this type of code in CSLA.NET.
Here's the link to the CSLA.NET class called BusinessBase.cs which has a similar definition to what I've given above.