1

Imageine a rpg game.

I have a character. My character has equipment slots in a class called Equipment These slots can be equipped with items of several types: Armor, Weapon etc.). They all inherif from the class Item.

Each Itemfits into a certain Equipment Slot. Each Equipment Slot has a type:

public enum EquipmentSlotType
{
    Head,
    LeftHand,
    RightHand,
    BothHands,
    Chest,
    Waist,
    Legs,
    Feet,
    Neck,
    LeftRingFinger,
    RightRingFinger,
}

My Character Class is not that interesting:

public class Character
{
    public string Name { get; private set; }
    public Equipment Equipment { get; private set; }
}

here is my characters Equipment class:

public class Equipment
{
    public EquipmentSlot Head { get; private set; }
    public EquipmentSlot LeftHand{ get; private set; }
    public EquipmentSlot RightHand { get; private set; }
    public EquipmentSlot BothHands { get; private set; }
    public EquipmentSlot Chest { get; private set; }
    public EquipmentSlot Waist { get; private set; }
    public EquipmentSlot Legs { get; private set; }
    public EquipmentSlot Feet { get; private set; }
    public EquipmentSlot Neck { get; private set; }
    public EquipmentSlot LeftRingFinger { get; private set; }
    public EquipmentSlot RightRingFinger { get; private set; }
    private System.Reflection.PropertyInfo[] propertyInfos;
    public Equipment()
    {
        Head = new EquipmentSlot(EquipmentSlotType.Head, false);
        LeftHand = new EquipmentSlot(EquipmentSlotType.Head, false);
        RightHand = new EquipmentSlot(EquipmentSlotType.RightHand, false);
        BothHands = new EquipmentSlot(EquipmentSlotType.BothHands,false);
        Chest = new EquipmentSlot(EquipmentSlotType.Chest,false);
        Waist = new EquipmentSlot(EquipmentSlotType.Waist,false);
        Legs = new EquipmentSlot(EquipmentSlotType.Legs,false);
        Feet = new EquipmentSlot(EquipmentSlotType.Feet, false);
        Neck = new EquipmentSlot(EquipmentSlotType.Neck, false);
        LeftRingFinger = new EquipmentSlot(EquipmentSlotType.LeftRingFinger, false);
        RightRingFinger = new EquipmentSlot(EquipmentSlotType.RightRingFinger, false);
        
        propertyInfos = typeof(Equipment).GetProperties();
        
    }

}
    public bool EquipItemFromInventory(EquippableItem item, Character character)
    {
        
        // this needs fixing:
        var x = propertyInfos.First(pi => pi.Name.ToString() == item.EquipmentSlotType.ToString());
        var y = character.Equipment. .GetProperty(x.Name).SetValue(character, item.);

        
        
        if (item.EquipmentSlotType == EquipmentSlotType.BothHands)
        {
            LeftHand.IsUsed = true;
            RightHand.IsUsed = true;
            BothHands.IsUsed = true;
            BothHands.Item = item;
            return true;
        }
        else
        {
            switch (item.EquipmentSlotType)
            {
                case EquipmentSlotType.Head:
                    Head.IsUsed = true;
                    Head.Item = item;
                    return true;

                case EquipmentSlotType.Chest:
                    Chest.IsUsed = true;
                    Chest.Item = item;
                    return true;

                case EquipmentSlotType.LeftHand:
                    LeftHand.IsUsed = true;
                    LeftHand.Item = item;
                    return true;

                case EquipmentSlotType.RightHand:
                    RightHand.IsUsed = true;
                    RightHand.Item = item;
                    return true;

                case EquipmentSlotType.Waist:
                    Waist.IsUsed = true;
                    Waist.Item = item;
                    return true;

                case EquipmentSlotType.Legs:
                    Legs.IsUsed = true;
                    Legs.Item = item;
                    return true;

                case EquipmentSlotType.Neck:
                    Feet.IsUsed = true;
                    Feet.Item = item;
                    return true;
                
                case EquipmentSlotType.LeftRingFinger:
                    Feet.IsUsed = true;
                    Feet.Item = item;
                    return true;
                
                case EquipmentSlotType.RightRingFinger:
                    Feet.IsUsed = true;
                    Feet.Item = item;
                    return true;
                
                default:
                    return false;
            }
        }
    }
}       

I know that the switch statement is too big and should be refactored. I am quite sure I should use reflection, but I cannot figure out how to do it... You can see my "result" above.

var x = propertyInfos.First(pi => pi.Name.ToString() == item.EquipmentSlotType.ToString());

This actually seems to find the correct equipmentslot. I pass in my bow which derives from Weapon and thus from Item, during debugging, I see x having a name of BothHands, which is correct. The bowhas an EquipmentSlotTypeof BothHands.

So I think I have the right propery, but I cannot figure out what to pass into .SetValue . It requires me to provide an object, but I cannot figure out which one :(

I added Characterto the method public bool EquipItemFromInventory(EquippableItem item, Character character)so that I could pass in an instance of my character.

Could somebody please show me how to make this reflection work and how to actually set the value correctly?

If you need any more information, please let me know.

Thanks so much!!!!

soomon
  • 396
  • 2
  • 18
  • You should pass `this` as the object since you're calling `SetValue()` from the same object that contains the property. – itsme86 Oct 16 '20 at 22:58
  • 3
    I am quite sure you should avoid using reflection here. Reflection is best used for discovering and manipulating types that you do not have access to at compile time. But in this example, you seem to know all the types. Refactoring seems like a better choice. – Sean Skelly Oct 16 '20 at 23:12
  • 1
    What about using a `Dictionary`, and then using `item.EquipmentSlotType` as the key to get the desired slot? This avoids the `switch` statement. (You would just need special handling for 'BothHands'.) Also, it seems the `IsUsed` property of a slot can be simplified to a read-only property that returns `Item != null`, rather than forcing yourself to keep updating the bool. – Sean Skelly Oct 16 '20 at 23:15
  • Hi @SeanSkelly thanks for your reply! I will try to go with your suggestion! Thanks so much!! – soomon Oct 17 '20 at 11:28

0 Answers0