Hello!
I need some help choosing the right pattern for my business object.
There is a general parent which is divided into three specialized parents, and there is a general child which is divided into three specialized children, too. The ChildA should be associated only with its ParentA, and ChildB with ParentB, and so on.
For now I have this:
public
abstract class Parent : BusinessBase<Parent>I don't like the fact to have an abstract child collection and a concrete child collection for each concrete child object. Is that the "right" way? Or is there another nicer solution? Am I right, that I would have to do some if or switch checks, when I use one child collection only (without abstract concrete collections)?
Yavuz
Hi Anthony!
Thank you for your answer. I can see that now AddNewChild() is implemented in the base collection class. However I have to implement one empty concrete collection class per concrete child classes. I was looking for an solution where I have only one non-abstract collection class which can handle each concrete child class. I have achieved that with a different generic collection class (see code below), so I can do this:
ParentA parentA = ParentA.NewParentA();Each concrete parent class's child collection member (Childs) is of type Childs<ConceteChild>. Adding a new child to the collection returns the right concrete child object. While implementing the child collection member in each of the concrete classes, I can't do this:
Parent parentA = ParentA.NewParentA();This is my solution so far:
public abstract class Parent : BusinessBase<Parent>
{
// general Parent properties
protected Parent() {}
}
public class ParentA : Parent
{
// special ParentA properties
private Childs<ChildA> _childs = new Childs<ChildA>();
public Childs<ChildA> Childs { get { return _childs; } }
public static ParentA NewParentA()
{
return DataPortal.Create<ParentA>();
}
protected ParentA() {}
}
public class ParentB : Parent
{
// special ParentB properties
private Childs<ChildB> _childs = new Childs<ChildB>();
public Childs<ChildB> Childs { get { return _childs; } }
public static ParentB NewParentB()
{
return DataPortal.Create<ParentB>();
}
protected ParentB() {}
}
public abstract class Child : BusinessBase<Child>
{
// general Child properties
protected Child() {}
}
public abstract class Child<T> : Child
{
internal static T NewChild()
{
return DataPortal.Create<T>();
}
protected Child() {}
}
public class ChildA : Child<ChildA>
{
// special ChildA properties
protected ChildA() {}
}
public class ChildB : Child<ChildB>
{
// special ChildB properties
protected ChildB() {}
}
public class Childs<T> : BusinessListBase<Childs<T>, Child<T>> where T : Child<T>
{
internal Childs() {}
public T AddNewChild()
{
var c = Child<T>.NewChild();
Add(c);
return c;
}
}
I haven't figured out yet how to implement the Childs member within the abstract parent class, so it returns the right child object based on the type of the parent.
Yavuz
selim51:I was looking for an solution where I have only one non-abstract collection class which can handle each concrete child class....
I haven't figured out yet how to implement the Childs member within the abstract parent class, so it returns the right child object based on the type of the parent.
You said in your OP that you didn't like having to create specific parent and child classes to match up your parents and children. Why? What about that bothers you? Because I think it's probably the better option.
In the end, I don't think you're going to get what you want without developing some if/switch code, as you mentioned earlier. While that would certainly give you what you want, I don't think it's a better solution than simply creating concrete parents that return the appropriate concrete children, especially if you have behaviors specific to the concrete subtypes. The code is much simpler to follow, and it keeps you from having to deal with a lot of headaches and casting. The single-parent, single-collection solution is essentially mixing responsibilities, and as your needs change with the parent/child combinations, trying to maintain that within one class only makes it more complex.
If you want to create an IoC container, as Anthony suggests, then by all means, go ahead. But you're still creating a match between a concrete parent type and concrete child type. You're just doing it in your IoC configuration, instead of writing the code yourself.
HTH
- Scott
Thank You for your arguments Scott!
tmg4340:You said in your OP that you didn't like having to create specific parent and child classes to match up your parents and children.
Maybe You haven't understood or I haven't clearly expressed myself. I didn't say I don't like having specific parent and child classes. They have to be there because they are my business object. I meant that I dont't like having specific child collection classes, for each specific child class one specific child collection class. Anthony's generic abstract child collection class has reduced implementing AddNewChild() to one time in the base class. In my original approach I had to implement it n times in very similar ways (one in each specific child collection class).
I assumed that I will not have specific behaviours for the child collections, so I get rid of the specific child collection classes by turning Anthony's generic abstract child collection class to a generic non-abstract one.
Following the CSLA pattern for creating new business objects through static methods (factories) I had to change my abstract child class to a generic one, too, because T.NewChild() does not work. This has the side effect that the concrete children don't need a factory method. As long as the process of creating children in each concrete child is similar this is good.
tmg4340:... I don't think it's a better solution than simply creating concrete parents that return the appropriate concrete children, especially if you have behaviors specific to the concrete subtypes....
If you want to create an IoC container, as Anthony suggests, then by all means, go ahead. But you're still creating a match between a concrete parent type and concrete child type.
In the original post each concrete parent returned concrete collections with concrete children in it. Now each concrete parent return the same generic colection which holds that concrete parent's concrete children. Simply by matching them in this way: Childs<ConcreteChild> _childs. I am aware of that I have to match parents with their children. I have never said that I don't want that. For now the _childs field is declared in each of the concrete parent, so I can't access it after casting a concrete parent to its base abstract parent type.
When shifting the _childs field to the abstract parent class the question is which type does it have? Childs<Child> and Childs<Child<T>> result in a compilation error.
If there is no solution until the next few days I will use my original approach because I have to finish my project
Yavuz
Copyright (c) Marimer LLC