Enumeration class matching

Hi I have an element of an abstract class. Classes like Food, Weapon, etc. are inherited by this class. All information about these elements is stored in the database, the C # code work matches the exact class and matches it using an Enum, which is also stored in the database column as a whole. My problem is that this stupid code is everywhere I have to use the methods of the 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 constructor parameter of the Food, Weapon, etc. it is an object from the database that allows you to know the object about its fields.

Is this some material to help me match these types without this code? It annoys me very much when I look at it.

+3


source to share


2 answers


You can use factory or creational method to create a 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. For example. your current code will look like this:



var item = CreateItem(userItem);
item.UseItem(sender); // you don't care about specific type of item

      

Note. EF can use the discriminator column to automatically create objects of the appropriate type.

+4


source


Just register your build actions once:

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's the 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 is using a DI container like unit or somth:

UnityContainer.RegisterType<IItemBase, Food>("ItemType.Food");
UnityContainer.RegisterType<IItemBase, Weapon>("ItemType.Weapon");

      

and allow

 var item1 = UnityContainer.Resolve<IItemBase>(ItemType.Food.ToString());

      

+2


source







All Articles