在这种情况下,更换开关块和枚举的正确方法是什么(C#)? [英] What is a correct way of replacing the switch block and Enum in this situation (C#)?

查看:168
本文介绍了在这种情况下,更换开关块和枚举的正确方法是什么(C#)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果它有帮助,下面的问题是在我正在建立的游戏的上下文中。

If it helps, the following question is in the context of a game I am building.

在几个不同的地方,我有以下场景。存在一个父类,对于这个例子叫做Skill,我有一些子类实现父类的方法。还有另一个父类,我们称之为Vocation。这些技能需要列在不同的职业分类中。然而,这些技能需要适用于任何使用任何给定职业的游戏。

In a few different places I have the following scenario. There exists a parent class, for this example called Skill, and I have a number of sub-classes implementing the methods from the parent class. There also exists another parent class that we will call Vocation. The skills need to be listed in different sub-classes of Vocation. However, those skills need to be available for anything in the game that uses any given vocation.

我当前的设置是将一个名为Skill.Id的枚举,以便Vocation包含该枚举值的集合,当游戏中的一个实体占用该职位该集合被传递到另一个类,称为SkillFactory。 Skill.Id每次创建一个新的技能子类时需要一个新的条目,以及一个新的子类构造函数的切换块中的一个例子。

My current setup is to have an Enum called Skill.Id, so that Vocation contains a collection of values from that Enum and when an entity in the game takes on that Vocation the collection is passed into another class, called SkillFactory. Skill.Id needs a new entry every time I create a new Skill sub-class, as well as a case in the switch block for the new sub-classes' constructor.

ie:

//Skill.Id
Enum{FireSkill,WaterSkill,etc}

//SkillFactory
public static Skill Create(Skill.Id id)
{
    switch(id)
    {
        case Skill.Id.FireSkill:
             return new FireSkill();
        //etc
    }
}

,但是使用枚举和切换块之间的感觉就像我需要解决这个问题的开销更多。有没有更优雅的方式来创建这些技能子类的实例,但仍允许Vocation包含一组识别可以使用的技能的集合?

This works perfectly fine, but using the enum and switch block as a go between feels like more overhead than I need to solve this problem. Is there a more elegant way to create instances of these Skill sub-classes, but still allows Vocation to contains a collection identifying the skills it can use?

编辑:我是只要Vocation可以包含允许任意实例化技能子类的集合,就可以抛出枚举和关联的切换块。

I am fine throwing out the enum and associated switch block, so long as Vocation can contain a collection that allows arbitrary instantiation of the Skill sub-classes.

推荐答案

您可以使用字典< Skill.Id,Func< Skill>> 并将其用于实例化。

You can make a Dictionary<Skill.Id, Func<Skill>> and use it to instantiate.

在构造函数中:

Dictionary<Skill.Id, Func<Skill>> creationMethods = new Dictionary<Skill.Id, Func<Skill>>();
public SkillFactory()
{
     creationMethods.Add(Skill.Id.FireSkill, () => new FireSkill());
     creationMethods.Add(Skill.Id.WaterSkill, () => new WaterSkill());
}

然后,您的Create方法变为:

Then, your Create method becomes:

public static Skill Create(Skill.Id id)
{
     return creationMethods[id]();
}

认为,这不是更好 - 除了它允许你将其扩展到每个ID的其他功能,而不会在需要时重复交换块。 (只是放在字典的价值方面)。

Granted, this isn't much better - except that it does allow you to extend this to other functionality that's per ID without duplicating the switch block if that becomes a requirement. (Just put more into the value side of the Dictionary.)

从长远来看,彻底摆脱这个枚举可以对扩展性有好处。然而,这将需要更精细的改变。例如,如果您使用MEF,您可以在运行时导入一组 SkillFactory 类型,并通过单个将它们与元数据(通过元数据)相关联ImportMany 。这将允许您添加新的技能子类,而无需更改工厂,并通过名称或其他机制来引用它们。

That being said, in the long run, getting rid of the enum entirely can be a good benefit for extensibility. This will require a more elaborate change, however. For example, if you used MEF, you could import a set of SkillFactory types at runtime and associate them to a name (via metadata) via a single ImportMany. This would allow you to add new Skill subclasses without changing your factory, and refer to them by name or some other mechanism.

这篇关于在这种情况下,更换开关块和枚举的正确方法是什么(C#)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆