0

I have below simple object model where Manager class consist List Of Child objects and Child object must have reference to it's parent object:

public class ManagerBase<T1> where T1 : ChildBase<???> { public ManagerBase() { ChildObjects = new List<T1>(); } public List<T1> ChildObjects { get; set; } } public class ChildBase<T1> where T1 : ManagerBase<???> { public ChildBase(T1 parentMgr) { ParentMgr = parentMgr; ParentMgr.ChildObjects.Add(this); } public T1 ParentMgr { get; set; } } 

Above are BASE classes. Now, below are inherited sample Manager and Child classes. I don't know how to make below classes to compile as above BASE classes are not valid yet. Could you pls help? Thanks.

public class CatalogManager : ManagerBase<Catalog> { } public class Catalog : ChildBase<CatalogManager> { } 

To provide more clear idea: I have BASE Manager class, BASE Child Object class. There are different type of inherited Managers (CatalogManager, DocumentManager etc.) and different type of Child Objects (Catalog, Document etc). Now, each Manager must consist of List not List. F.e: CatalogManager with List, DocumentManager with List. At the same time, each child object must have reference to it's Manager. In other words, I need strong typing instead of using Base classes. Hope it clear. Thanks for your time.

0

1 Answer 1

1

You can achieve that by creating non-generic base classes for the generic base classes. Answer updated to avoid type casting; to do so, ChildObjects property had to be IEnumerable<T> because it's type parameter is covariant, while classes, IList<T>, and ICollection<T> are contravariant.

public abstract class ManagerBase { protected ManagerBase() { innerChildObjectList = new List<ChildBase>(); } private IList innerChildObjectList; public IEnumerable<ChildBase> ChildObjects { get { foreach (ChildBase child in innerChildObjectList.OfType<ChildBase>()) yield return child; } } public void AddChild<T>(T child) where T : ChildBase { innerChildObjectList.Add(child); } public void RemoveChild<T>(T child) where T : ChildBase { innerChildObjectList.Remove(child); } public bool ContainsChild<T>(T child) where T : ChildBase { return innerChildObjectList.Contains(child); } //Add 'Insert', 'RemoveAt' methods if needed. } public abstract class Manager<T> : ManagerBase where T : ChildBase { public new IEnumerable<T> ChildObjects { get { return base.ChildObjects.OfType<T>(); } } } public abstract class ChildBase { protected ChildBase(ManagerBase mgr) { ParentMgr = mgr; } private ManagerBase parentMgr; public ManagerBase ParentMgr { get { return parentMgr; } set { if (parentMgr != null && parentMgr.ContainsChild(this)) parentMgr.RemoveChild(this); parentMgr = value; parentMgr.AddChild(this); } } } public abstract class Child<T> : ChildBase where T : ManagerBase { protected Child(T mgr) : base (mgr) { } public new T ParentMgr { get { return base.ParentMgr as T; } set { base.ParentMgr = value; } } } 

Now this will be okay:

public class CatalogManager : Manager<Catalog> { } public class Catalog : Child<CatalogManager> { public Catalog(CatalogManager parentMgr) : base(parentMgr) { } } 
Sign up to request clarification or add additional context in comments.

1 Comment

Is it a good practice as it involves casting everytime while you access ParentManager or Childs? Thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.