I am working on a UI system for a MonoGame project.
I created one large class called UserInterface
. Inside this class, there are nested classes such as Button
, Checkbox
, Scrollbar
, etc. which all inherit from one base class called UIObject
. Every object on the UI is stored in a private System.Collections.Generic.List<UIObject>
called canvas
.
The programmer using this class can easily add a new object to the canvas by using the public method UserInterface.Add(string name, UIObject obj)
. When the programmer adds an object to the canvas, they assign it a name so that it can be found in the list.
My problem arises as I try to make a public method that will return the object which has a specific name.
My attempt looks likes this:
public UIObject GetObject(string nameOfObject)
{
return canvas.System.Linq.FirstOrDefault(o => o.Name == nameOfObject);
}
The issue: The object returned by this method is always a UIObject
and not the inheriting class that the original object belongs to. That means it can't access the properties of the said original class. For example, if I wanted to check whether or not a Button
on the canvas was pressed I would do the following:
UserInterface ui = new UserInterface();
ui.Add("nameOfButton", new Button());
if (ui.GetObject("nameOfButton").IsPressed)
{
// Do stuff
}
However, this will not work because the property IsPressed
belongs to the Button
class and the returned object is a UIObject
.
How can I return the objects from the canvas using their original type?
SOLVED:
Big thanks to Austin Brunkhorst for pointing me towards generics!
Working method:
public T GetObject<T>(string nameOfObject) where T : UIObject
{
return canvas.System.Linq.FirstOrDefault(o => o.Name == nameOfObject) as T;
}
Method is called like so:
UserInterface ui = new UserInterface();
ui.Add("nameOfButton", new Button());
if (ui.GetObject<Button>("nameOfButton").IsPressed)
{
// Do stuff
}
You will need to cast the UIObject
as the type you're looking to use. In this case, Button
.
Button slickButton = (Button)ui.GetObject("nameOfButton");
Careful! This will throw an exception if the object is not in fact a Button
.
Alternatively, you can use the as
operator, which evaluates to null
if the object isn't a Button
.
Button slickButton = ui.GetObject("nameOfButton") as Button;
I suggest looking into generics, as you can avoid this by explicitly stating the type you expect and have the method do the magic for you.
Button slickButton = ui.GetObject<Button>("nameOfButton");