Hi I have an abstract class Item. Classes like Food, Weapon, etc inherit by this class. All informations about this items are stored in the database, work of C# Code is match the exact class and match it by Enum which is also stored in the database column as integer. My problem is this stupid code wherever I have to use methods of Food, Weapon etc classes
if ((ItemType)userItem.ItemType == ItemType.Food)
{
Food food = new Food(userItem);
food.UseItem(sender);
}
else if ((ItemType)userItem.ItemType == ItemType.Weapon)
{
Weapon weapon = new Weapon(userItem);
weapon.UseItem(sender);
}
In the parameter of constructor of Food, Weapon etc. classes is the the object from database to let know object about its fields.
Is some kind of stuff that will help me to match this types without this code? It really annoys me when I'm looking at it.
You can use factory or creational method to create specific type of item:
public Item CreateItem(UserItem userItem)
{
var itemType = (ItemType)userItem.ItemType;
switch(itemType)
{
case ItemType.Food: return new Food(userItem);
case ItemType.Weapon: return new Weapon(userItem);
// etc
default:
throw new NotSupportedException($"Item type {itemType} is not supported");
}
}
Then use this method to create items and use them. E.g. your current code will look like:
var item = CreateItem(userItem);
item.UseItem(sender); // you don't care about specific type of item
Note: EF can use discriminator column to create entities of appropriate type automatically.
Just register building actions one time:
var builder = new ItemBuilder()
.RegisterBuilder(ItemType.Food, () => new Food())
.RegisterBuilder(ItemType.Weapon, () => new Weapon());
and use it later like this:
var item1 = builder.Build(ItemType.Food);
item1.UseItem(sender)
and here a builder code:
public class ItemBuilder
{
public ItemBase Build(ItemType itemType)
{
Func<ItemBase> buildAction;
if (itemBuilders.TryGetValue(itemType, out buildAction))
{
return buildAction();
}
return null;
}
public ItemBuilder RegisterBuilder(ItemType itemType, Func<ItemBase> buildAction)
{
itemBuilders.Add(itemType, buildAction);
return this;
}
private Dictionary<ItemType, Func<ItemBase>> itemBuilders = new Dictionary<ItemType, Func<ItemBase>> ();
}
Another option use a DI container like unity or somth:
UnityContainer.RegisterType<IItemBase, Food>("ItemType.Food");
UnityContainer.RegisterType<IItemBase, Weapon>("ItemType.Weapon");
and resolve
var item1 = UnityContainer.Resolve<IItemBase>(ItemType.Food.ToString());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With