Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matching class by enum

Tags:

c#

enums

class

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.

like image 665
Przemysław P. Avatar asked May 17 '26 19:05

Przemysław P.


2 Answers

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.

like image 145
Sergey Berezovskiy Avatar answered May 19 '26 08:05

Sergey Berezovskiy


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());
like image 35
gabba Avatar answered May 19 '26 07:05

gabba



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!