【问题标题】:Matching class by enum通过枚举匹配类
【发布时间】:2017-04-20 16:46:35
【问题描述】:

您好,我有一个抽象类 Item。 Food、Weapon 等类由此类继承。有关此项目的所有信息都存储在数据库中,C# 代码的工作是匹配确切的类并通过 Enum 进行匹配,Enum 也以整数形式存储在数据库列中。我的问题是这个愚蠢的代码,无论我必须使用食物、武器等类的方法

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);
}

在Food、Weapon等类的构造函数的参数中是来自数据库的对象,让对象知道它的字段。

是否有某种东西可以帮助我在没有此代码的情况下匹配这些类型?当我看着它时,它真的让我很烦。

【问题讨论】:

标签: c# class enums


【解决方案1】:

您可以使用工厂或创建方法来创建特定类型的项目:

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");
    }
}

然后使用此方法创建项目并使用它们。例如。您当前的代码将如下所示:

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

注意:EF 可以使用 discriminator 列自动创建适当类型的实体。

【讨论】:

    【解决方案2】:

    只需注册一次构建​​操作:

    var builder = new ItemBuilder()
        .RegisterBuilder(ItemType.Food, () => new Food())
        .RegisterBuilder(ItemType.Weapon, () => new Weapon());
    

    然后像这样使用它:

       var item1 = builder.Build(ItemType.Food);
       item1.UseItem(sender)
    

    这里有一个构建器代码:

    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>> ();
    }
    

    另一种选择是使用 DI 容器,例如 unity 或 somth:

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

    并解决

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多