Reputation: 617
I'm writing a game and I have a Crate class which holds Item-s of type T varying by crate. I've set this up with Generics like this:
public class Crate<I> : Item
where I : Item
{
private List<I> contents = new List<I>();
//...
}
I'm currently writing a "buy" screen where you choose items, and then crates of those items are delivered. Depending on what stage the player is in the game, certain items are/aren't available. Therefore I have a list of currently available items in an array.
What I want to do is create Crates based on that array.
For example, my array might be
public static List<Item> CurrentlyAvailableItems= new List<Item>() { new Linen(), new Food() };
From here, I want to create buttons to generate Crates of those items. At the moment the only way I can think to do it is with a giant IF loop which needs updating every time i create new items like this:
for (int i = 0; i < GV.CurrentlyAvailableItems.Count; i++)
{
Item item = null;
if (GV.CurrentlyAvailableItems[i] is Linen) item = new Crate<Linen>();
else if (GV.CurrentlyAvailableItems[i] is Food) item = new Crate<Food>();
Add(new BuyButton(item));
}
What I want to be able to do is something like:
for (int i = 0; i < GV.CurrentlyAvailableItems.Count; i++)
{
Type t = GV.CurrentlyAvailableItems[i].GetType();
Crate<t> crate = new Crate<t>();
Add(new BuyButton(crateToBuy ));
}
Is this possible?
Upvotes: 1
Views: 100
Reputation: 31146
You can do it with the dynamic keyword and function overloading for each derived type if you have only a few of them, or with reflection (see Jon Skeet's answer):
BuyButton CreateButton(MyDerivedItem foo)
{
return new BuyButton(Crate<MyDerivedItem>());
}
// ... and in your code:
Add(CreateButton((dynamic)(GV.CurrentlyAvailableItems[i])));
Upvotes: 2
Reputation: 1502816
You can do it with reflection:
// TODO: Consider using a foreach loop over GC.CurrentlyAvailableItems
Type itemType = GV.CurrentlyAvailableItems[i].GetType();
Type crateType = typeof(Crate<>).MakeGenericType(t);
Item crate = (Item) Activator.CreateInstance(crateType);
Add(new BuyButton(crate));
Note that this won't be terribly efficient - but it may be good enough. If it's not, you may want a Dictionary<Type, Func<Item>>
or something like that.
Upvotes: 4