vendredi 16 octobre 2020

reflection - how to set the value

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!!!!





Aucun commentaire:

Enregistrer un commentaire