Recursive Lookup of generic List C# using LINQ - c#

I have generic list of a custom class which has 2 properties. These properties store the raltionship between on form and another form. The list is structured as a hierachical list (parent / child ) relationship. What I want to be able to do is get a list of all forms based on a parent form reference which will be passed to a function. I am thinking the best way to go about this is with a LINQ query using a recursive approach. I am sure someone can point me in the right direction
This is the class used in the list
class FormStack {
#region Declares
private Form _form;
private Form _parent;
#endregion
#region Constructor
static FormStack()
{
}
#endregion
public Form Form
{
get { return _form; }
set { _form = value; }
}
public Form Parent
{
get { return _parent; }
set { _parent = value; }
}
}
So I would like to be able to Call a method and pass a form reference to the function and get all the children form related to this parent.
This is some of the code I have been stumbling with
// create a lookup list
var list = formStack.ToLookup( p => object.ReferenceEquals( p.Parent, parent ) );
// create a function
Func<IEnumerable<Form>, IEnumerable<Form>> recurse = null;
recurse = qs =>
{
return
qs
.Concat(
from q in qs
from q2 in recurse( list[] )
select q2 );
};
// filter the list
var children = recurse( list[parent] ).ToList();
I have a winform application which has standard CRUD functionality. Lets say there is a list of customers and each customer can have multiple address and each one of these addresses have multiple buildings, the way I have structured the forms is there is a list of customers, from this list you can open a detail form for a particular customer. This form has the details of the customer and all the addresses in a list. This list allows the user to now selected an address in the list and open the address details form which has a list of buildings and so on.... My problem is I want to close the customer detail and all the related forms for this customer. My idea was to keep of the relationship between the forms, but maybe I there is a better way???

here is what I made up:
Create a base Form for all your Forms:
public class MyFormBase : Form
{
public MyFormBase()
{
FormRepository.RegisterForm(this);
}
public MyFormBase(MyFormBase parent)
: this()
{
Parent = parent;
}
public MyFormBase Parent { get; set; }
}
Each Form can only have one Parent that is passed in the constuctor.
Create a Repository (or something simiar) to store your forms -> I do not want to store all children in the Form itself
//infrastructure - simulated with a static class
public static class FormRepository
{
private static List<MyFormBase> _allForms = new List<MyFormBase>();
public static void RegisterForm(MyFormBase form)
{
_allForms.Add(form);
}
public static void CloseFormAndChildren(MyFormBase form)
{
_allForms.Where(x => x.Parent.Equals(form)).ToList().ForEach(x => CloseFormAndChildren(x));
form.Close();
}
}
Call CloseFormAndChildren on any form you want to close (including the children). This could be called in the closing event...

Okay, it sounds to me like you have two issues. One is a syntax error (recurse(list[]) is wrong), but the other is that your FormStack isn't really a stack. It's just two forms, with no way to create a recursive chain. I think you want this:
public class FormStack : IEnumerable<Form> // or just implement SelectMany
{
public Form Form { get; set; }
public FormStack Parent { get; set; }
//implement IEnumerable<Form> or the SelectMany method
}
Then I think you can just do this, but it seems like an awkward thing to do:
Func<FormStack, IEnumerable<Form>> recurse = qs =>
{
return from q in qs
select (new[] { qs.Form }).Concat(recurse(qs.Parent));
};
var list = recurse(formStack).ToList();
That's if you're insisting on the query syntax.
If I were you, though, I'd forget all that and implement an IEnumerator<Form> to do it all for you:
public class FormStack : IEnumerable<Form>
{
public Form Form { get; set; }
public FormStack Parent { get; set; }
public IEnumerator IEnumerable:GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
public IEnumerator<Form> GetEnumerator()
{
return new FormStackEnumerator(this);
}
}
public class FormStackEnumerator : IEnumerator<Form>
{
private FormStack _stack;
private FormStack _first;
public Form Current { get { return _stack.Form; } }
object IEnumerator.Current { get { return Current; } }
public FormStackEnumerator(FormStack stack)
{
_stack = stack;
_first = stack;
}
public bool MoveNext()
{
if (_stack.Parent == null)
{
return false;
}
_stack = _stack.Parent;
return true;
}
public void Reset() { _stack = _first; }
void IDisposable.Dispose() { }
}
Then all you'd need to do in your main code is this:
var list = new List<Form>();
foreach (var node in formStack)
{
list.Add(node.Form);
}
By the way, I just looked up the Form class (I'm not a WinForms developer) and the Forms themselves have a Parent member. So you don't really need to wrap them in a node-type construct; they're already nodes! That makes everything easy:
var list = new List<Form>();
Action<Control> recurse = target =>
{
var form = target as Form;
if (form != null)
{
list.Add(form);
recurse(target.Parent);
}
}

Related

Dictionary of generic lists of controls

I'm working on a product calculator program. Inside the app, the rep sale person can search for a client ID and the app shows him what services he can offer to client and his provision for sale. The form is generated acording to data i download from database.
Right now I'm trying to store generated controls in lists. Every time a search is made, I dispose of controls and clear the lists. The thing i cant seem to get working is to store all the lists in single dictionary.
Something like this...
public class ListOfControls<T> : IListOfControls<T> where T : Control
{
private readonly List<T> _controlsList;
public ListOfControls()
{
_controlsList = new List<T>();
}
public void AddControll(T control)
{
_controlsList.Add(control);
}
public T this[int number]
{
get
{
return _controlsList[number];
}
}
public void ClearControls()
{
_controlsList.Clear();
}
public T Last()
{
return _controlsList.Last();
}
}
class DictionaryOfControlsLists
{
//will be private - public only for test
public readonly Dictionary<string, IListOfControls<Control>> _dictionaryOfLists;
public DictionaryOfControlsLists()
{
_dictionaryOfLists = new Dictionary<string, IListOfControls<Control>>();
}
//Other code....
}
Now trying to implement...
DictionaryOfControlsLists _testDict = new DictionaryOfControlsLists();
_testDict._dictionaryOfLists.Add("test", new ListOfControls<Label>());
Sadly this wont work...Any ideas? THANKS
What you need is something like this:
class DictionaryOfControlsLists
{
private readonly Dictionary<Type, IListOfControls<Control>> _dictionaryOfLists = new Dictionary<Type, IListOfControls<Control>>();
public void Add<T>(T control) where T : Control
{
if (!_dictionaryOfLists.ContainsKey(typeof(T)))
{
_dictionaryOfLists[typeof(T)] = new ListOfControls<Control>();
}
_dictionaryOfLists[typeof(T)].AddControl(control);
}
public T Get<T>(int number) where T : Control
{
if (!_dictionaryOfLists.ContainsKey(typeof(T)))
{
_dictionaryOfLists[typeof(T)] = new ListOfControls<Control>();
}
return _dictionaryOfLists[typeof(T)][number] as T;
}
}
Then you can do this:
DictionaryOfControlsLists _testDict = new DictionaryOfControlsLists();
_testDict.Add<Label>(new Label());
Label label = _testDict.Get<Label>(0);
If you need to extend this to have a string key then you need to implement a double dictionary within DictionaryOfControlsLists to handle it - something like a Dictionary<Type, Dictionary<string, IListOfControls<Control>>>.

Universal Apps using Unity & Prism

I am learning the whole new Universal Apps creation together with Prism and Unity, but I got a few questions I am not sure about:
I have the following simple data object:
public class Customer : IEditableObject, IEquatable<Customer>
{
private Customer backup;
public string Name { get; set; }
public string Surname { get; set; }
public DateTime DateOfBirth { get; set; }
public void BeginEdit()
{
this.backup = this.MemberwiseClone() as Customer;
}
public void CancelEdit()
{
this.Name = this.backup.Name;
this.Surname = this.backup.Surname;
this.DateOfBirth = this.backup.DateOfBirth;
}
public void EndEdit()
{
this.backup = this.MemberwiseClone() as Customer;
}
public bool WasChangeMade()
{
if (this.Equals(backup))
return false;
else
return true;
}
public bool Equals(Customer other)
{
return this.Name == other.Name &&
this.Surname == other.Surname &&
this.DateOfBirth == other.DateOfBirth;
}
}
Under my Main Page I have a simple ListBox, where I show collection of these Customers. Everything good so far.
Afterwards, when under my ListBox user selects any one of these Customer, then he can click Edit Settings button and edit properties of this selected Customer. It is a simple command:
cmd_EditCustomer = new DelegateCommand(() =>
{
_navigationService.Navigate(App.Experiences.Detail.ToString(), SelectedCustomer);
});
Which simply navigates to a new page (detail page, where user can do the changes) and the argument I pass here is the Selected Customer.
My DetailPage View Model looks like following:
public class DetailPageViewModel : ViewModel, Interfaces.IDetailPageViewModel
{
public DelegateCommand cmd_SaveChanges { get; set; }
public Customer SelectedCustomer { get; set; }
private readonly INavigationService _navigationService;
private readonly IDialogService _dialogService;
public DetailPageViewModel(INavigationService navigationService,
IDialogService dialogService)
{
_navigationService = navigationService;
_dialogService = dialogService;
InitializeCommands();
}
public override void OnNavigatedTo(object navigationParameter, NavigationMode navigationMode, Dictionary<string, object> viewModelState)
{
this.SelectedCustomer = navigationParameter as Customer;
this.SelectedCustomer?.BeginEdit();
}
private void InitializeCommands()
{
cmd_SaveChanges = new DelegateCommand(() =>
{
SelectedCustomer?.EndEdit();
_dialogService.Show("Changes Saved!");
_navigationService.Navigate(App.Experiences.Main.ToString(), null);
});
}
}
As you can see, this is a very simple application, which I only use for learning purposes. Here are my questions:
1) Is it good to pass Selected Customer in such a way as I did? (in the parameter of the INavigationService), or should I implement other logic?
2) When user makes a change to the Selected Customer and clicks Save Changes (the only command you can see there), it does not update the original Customer (from my original collection). How is this possible? How to achieve, that my Customer will be updated? Should I create PubSubEvent for this?
EDIT:
I have managed to locate the error - when user navigates back to MainPage, my MainPageViewModel is re-initializes, which re-populates collection of items. The question now is - how can I keep MainWindowViewModel alive thorough the applications life?
Re-populates collection of items from what?
You just need to save a new values, for example if you populate your customers from DB you have to call DB and save changes before navigate back etc, so after that when MainPageViewModel would be re-initializes you'll get your changes and changes performed by another users.
In the end, I found out that this was not a good way how to hold data in your application.
Based on what I have read, I should have implemented Repository Strategy, which is only referenced in a ViewModel such as:
public MainPageViewModel(IDataRepository dataRepository, INavigationService navService, ...){etc.}
Example of a simplified interface:
public interface IDataRepository
{
List<string> GetListOfStrings();
string GetUserEnteredData();
void SetUserEnteredData(string data);
}
This is how you initialize it in UnityContainer:
_container.RegisterType<IDataRepository, DataRepository>();
You can read more from Patterns & Practices team in here:
https://prismwindowsruntime.codeplex.com/

Too many calculated properties in my class

I have class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}

How do i convert a class (which is derived from a generic "base" class) to that generic "base" class

I created a base class ("Element") and a base list class ("Elements") as generic class.
The generic list class should only be able to contain classes, which are of Type "Element" of derived from "Element".
The "Element" class should own a "ParentRoot" property, which should contain the base list class ("Elements")!
public class Element
{
public Elements<Element> ParentRoot { get; set; }
}
public class Elements<T> : List<T> where T : Element
{
}
Now i create two classes and two list classes which are derived form the classes above. But i'm failing on setting the "ParentRoot" property:
public class Ceiling : Element
{
public Ceiling(Ceilings parent)
{
Parent = parent;
ParentRoot = parent;
}
public Ceilings Parent { get; set; }
}
public class Ceilings : Elements<Ceiling>
{
}
public class Wall : Element
{
public Wall(Walls parent)
{
Parent = parent;
ParentRoot = parent;
}
public Walls Parent { get; set; }
}
public class Walls : Elements<Wall>
{
}
I get two errors at:
ParentRoot = parent;
Cannot implicitly convert type "Ceilings" to "Elements"
Cannot implicitly convert type "Walls" to "Elements"
Is there a solution for this problem?
Thanks for any help!
EDIT:
OK, i have to be a bit more specific.
I expanded the code a bit:
public class Room
{
public Room(Rooms parent)
{
Parent = parent;
}
public Rooms Parent { get; set; }
}
public class Rooms : List<Room>
{
}
public class Element
{
public Elements<Element> ParentRoot { get; set; }
public Rooms FindRoomsToElement()
{
Rooms rooms = new Rooms();
foreach (Room room in ParentRoot.Parent.Parent)
{
// Do stuff here
// if i rename the "ParentRoot" property to "Parent" and make it "virtual",
// and the other properties overwrite it with the "new" key, then this will
// get a null exception!
// i haven't testet it, but i think abstrakt will bring the same/similar result
// if i make the "ParentRoot" property IEnumerable, then there will no
// ParentRoot.Parent be available
}
return rooms;
}
}
public class Elements<T> : List<T> where T : Element
{
public Elements(Room parent)
{
Parent = parent;
}
public Room Parent { get; set; }
}
public class Ceiling : Element
{
public Ceiling(Ceilings parent)
{
Parent = parent;
//ParentRoot = parent;
}
public Ceilings Parent { get; set; }
}
public class Ceilings : Elements<Ceiling>
{
public Ceilings(Room parent) : base(parent)
{
}
}
public class Wall : Element
{
public Wall(Walls parent)
{
Parent = parent;
//ParentRoot = parent;
}
public Walls Parent { get; set; }
}
public class Walls : Elements<Wall>
{
public Walls(Room parent) : base(parent)
{
}
}
I hope this makes it more precise.
You aren't allowed to do this because if you could, you could put the wrong kind of elements into a List.
Elements<Ceilings> ceilings = someCeilings;
Elements<Element> parentRoot = ceilings; // Not allowed; imagine it is though.
Wall wall = someWall;
parentRoot.Add(wall); // Oops - we just added a wall to someCeilings!
If you can just treat the walls and/or ceilings as a sequence, you can do use IEnumerable<Element> instead (which works because IEnumerable<T> is "covariant"):
IEnumerable<Element> parentRoot = ceilings; // OK
This is OK because IEnumerable<Element> has no way to modify the original collection.
The problem is that, given a Generic<T> and a Child : Base, the type Generic<Base> is not a base of Generic<Child>. Generics are not base classes for their concrete implementations - they are templates out of which concrete implementations can be created and, in turn, the concrete implementations don't have a hierarchical relationship with each other. Consider the following snippet to understand why this is so:
var bananas = List<Banana>();
var fruits = (List<Fruit>)bananas; // If this was valid
fruits.Add(new Orange()); // Then this would be valid
// So we'd have an Orange to a list of runtime type List<Banana>
Therefore, your Elements<Element>, which is a case of the Generic<Base> I described above, cannot work as a base for the others. Your Ceilings and Walls are neither implicitly nor explicitly convertible to Elements<Element>.
A possible workaround would be to make ParentRoot a virtual or better yet an abstract property (if Element can be abstract) and override it in every subclass of Element to manually convert the Parent property to the Elements<Element> type.
For example, you could change your base and your generic like this:
public abstract class Element
{
public abstract Elements<Element> ParentRoot { get; }
}
public class Elements<T> : List<T> where T : Element
{
public Elements<T>() : base()
{
}
public Elements<T>(ICollection<T> collection) : base(collection)
{
}
}
Then, for every subclass, do the following:
public class Wall : Element
{
public Wall(Walls parent)
{
Parent = parent;
}
public Walls Parent { get; set; }
public override Elements<Element> ParentRoot
{
get
{
return new Elements<Element>(Parent);
}
}
}
Of course, modifications to the object returned by ParentRoot will not affect Parent. But this is okay semantically, because (as I described with the bananas and the oranges), you wouldn't want to accidentally add a Ceiling to a Walls just because it looks like an Elements<Element> at some point in the code.
Instead of this:
Parent = parent;
ParentRoot = parent;
try this
Parent = parent;
ParentRoot = new Elements<Element>();
ParentRoot.AddRange(parent);
My answer is based on seeing your code and think that you are trying to build a room with n elements.Using composition "has-a" or "is-part-of" and a freely take on factory pattern i think you can achieve this.In my code i based in a "room" "has" elements,if you think "elements" "is-a" "room"?...so elements is part of the room,and those elements in your case are ceiling and wall,now wall "is-a" element and ceiling "is-a" element of room,then naturaly i derived those from element but keeping a "reference" in room for element.About having a list of rooms i nested a private class,since there is no need(in my opinion) for wall or ceiling to have access to available rooms so in room class you do all the work.In room class i derived interface IRoomBuilder with proper methods,the ones uncommented are the ones you should use for creating for example a wall with some specifications and add to room,the commented ones are just for example purposes.I placed some user-side code for you to test.
public interface IRooms
{
List<Room> AvailableRooms();
}
public interface IRoomBuilder
{
//void MakeWall();
//void MakeWalls(int NumWalls);
//void MakeCeiling();
//void MakeCeilings(int NumCeilings);
void MakeElement(Element el);
void MakeElements(List<Element> elmts);
}
public class Room:IRoomBuilder
{
private List<Element> roomelements;
private readonly Rooms ShowRooms;
public List<Element> RoomElements
{
get { return roomelements; }
set { RoomElements.AddRange(value); }
}
public Room()
{
roomelements = new List<Element>();
ShowRooms = new Rooms();
}
public void MakeElement(Element el)
{
RoomElements.Add(el);
}
public void MakeElements(List<Element> elmts)
{
RoomElements.AddRange(elmts);
}
//public void MakeWall()
//{
// RoomElements.Add(Element.MakeElement(typeof(Wall).Name));
//}
//public void MakeWalls(int NumWalls)
//{
// for (int i = 0; i < NumWalls; i++)
// {
// RoomElements.Add(Element.MakeElement(typeof(Wall).Name));
// }
//}
//public void MakeCeiling()
//{
// RoomElements.Add(Element.MakeElement(typeof(Ceiling).Name));
//}
//public void MakeCeilings(int NumCeilings)
//{
// for (int i = 0; i < NumCeilings; i++)
// {
// RoomElements.Add(Element.MakeElement(typeof(Ceiling).Name));
// };
//}
public void AddRoom()
{
ShowRooms.Add(this);
}
public List<Room> GetAllRooms()
{
IRooms r = (IRooms)ShowRooms;
return r.AvailableRooms();
}
public override string ToString()
{
return "I am a room with " + RoomElements.Count.ToString() + " Elements";
}
private class Rooms : List<Room>,IRooms
{
List<Room> IRooms.AvailableRooms()
{
return this;
}
}
}
public abstract class Element
{
//this method is used for the commented methods
public static Element MakeElement(string name)
{
if (name == typeof(Ceiling).Name)
return new Ceiling() as Element;
else if (name == typeof(Wall).Name)
return new Wall() as Element;
else
throw new ArgumentException("Parameter not valid");
}
}
public class Ceiling : Element
{
//your implementation.
public override string ToString()
{
return "I am a ceiling";
}
}
public class Wall : Element
{
//your implementation.
public override string ToString()
{
return "I am a wall!";
}
}
Client-side code example:
Wall w = new Wall();
Ceiling c = new Ceiling();
Room r = new Room();
r.MakeElement(w);
r.MakeElement(c);
List<Element> NewElements = new List<Element>{ new Wall(), new Ceiling() };
r.MakeElements(NewElements);
//r.MakeWalls(5);
//r.MakeCeilings(6);
r.AddRoom();
foreach (Room room in r.GetAllRooms())
{
MessageBox.Show(room.ToString());
foreach (Element el in room.RoomElements)
{
MessageBox.Show(el.ToString());
}
}
Hope this helps.

Object Oriented Programming Nth Child

language specific (however, if you need a language please use C++/C# or Javascript). I trying to figure out how I would go about doing this, and how I would access the child objects from a parent object.
Say I have the following classes, and these are not written properly etc... :
Class: roomContainer (container of objects)
Class: Table (base class for a table, contains property of maximum-seats, current-number-of-seats, array of seats )
Class: Desk (extends Table, contains property for maximum draws, array of draws )
Class: seat (base class for seats, contains property of maximum-legs, arm-rest, back-rest)
Class: couch (extends seat, adds property maximum seats)
If I create an instance of roomContainer, and add within it's container a table, couch. Within the table I create multiple seats (or chairs), and a desk.
How would I be able to access the property of child objects property, when the parent has a container of different objects. I.e the roomContainer Container of objects, one of them is a table, and a desk - where the desk has different properties and an array of draws etc.. ?
You're looking for something called the Composite Design Pattern. This allows you to nest objects (as you described), and hold references to both the parent and the children (though some implementations do no maintain a parent reference - this is optional).
Here is an example implementation using your schema:
public static class Program // the supporting class definitions are below
{
public static void Main()
{
// create a root container
var room = new RoomContainer();
// create a child
var table = new Table(room, 4);
// put the table in the room
room.Add(table);
MakeMess(room);
}
// to show you how to access the properties
// if you don't already have a reference:
public static void MakeMess(RoomContainer room)
{
if(room == null)
{
throw new ArgumentNullException("room");
}
var seats = room.GetChildren<Table>().First().Seats.ToArray();
for (int index = 0; index < seats.Length; index++)
{
Console.WriteLine("You have kicked over Seat #{0}",(index+1).ToString());
}
}
}
// This is the base class of the components and provides the core functionality.
// You will want to make this object's interface minimal, so that the logic
// is consistent with all its children (without knowing what they might be in advance)
public abstract class Component
{
private readonly IList<Component> _children;
private readonly Component _container;
protected Component(Component container)
{
_container = container;
_children = new Component[] { };
}
public bool IsRoot { get { return _container == null; } }
public abstract bool IsContainer { get; }
public virtual void Add(Component component)
{
if (component == null)
{
throw new ArgumentNullException("component");
}
if (!IsContainer)
{
throw new NotSupportedException("Add is not supported by leaf components");
}
_children.Add(component);
}
public IEnumerable<T> GetChildren<T>()
where T: Component
{
if (!IsContainer)
{
throw new NotSupportedException("Only containers have children");
}
return _children.OfType<T>();
}
public IEnumerable<Component> Children
{
get
{
if (!IsContainer)
{
throw new NotSupportedException("Only containers have children");
}
return _children;
}
}
}
public class RoomContainer : Component
{
public RoomContainer() : base(null)
{
}
public override bool IsContainer { get { return true; } }
}
public class Table : Component
{
private readonly int _maximumSeatCount;
public Table(Component container, int maximumSeatCount) : base(container)
{
_maximumSeatCount = maximumSeatCount;
}
public override bool IsContainer { get { return true; } }
protected virtual bool CanAdd(Component component)
{
return component is Seat && MaximumSeatCount > CurrentSeatCount;
}
public override void Add(Component component){
if(CanAdd(component)){
base.Add(component);
}
else
{
throw new NotSupportedException("The component was an invalid child of Table and could not be added.");
}
}
public int MaximumSeatCount { get { return _maximumSeatCount; } }
public int CurrentSeatCount { get { return Seats.Count(); } }
public IEnumerable<Seat> Seats { get { return Children.OfType<Seat>(); } }
}
public class Seat : Component
{
// you can restrict the constructor to only accept a valid parent
public Seat(Table table) : base(table)
{
}
public override bool IsContainer
{
get { return false; }
}
}
If the all share common methods, for example Render(), Update(), SaveDetails(int Id), LoadDetails(int Id) then you could make them all inherit from a base class, or all impliment a common interface. This would remove the need for casting (below) when calling a common method (or accessing a common property).
To access properties unique to the derived class you would check the type of the child object, then cast the child object to access the property.
EDIT: Example:
foreach(Object obj in Room.ChildObjects)
{
if(obj is Desk)
{
Desk DeskObj = obj as Desk; // Cast the object reference as a desk.
DeskObj.MaxDraws = 50; // It's a big desk!
DestObj.Draws[1] = new Draw(); // ......
}
}
Something like this:
IEnumerable<Desk> desks = roomContainer.OfType<Desk>();
//Iterate and do stuff.
IEnumerable<Table> tables = roomContainer.OfType<Table>();
//Iterate and do stuff.

Categories

Resources