61

所以我在 XNA、C# 4.0 中创建一个游戏,我需要管理很多 PowerUps(在代码中都是从类“PowerUp”继承的),并处理我目前拥有的 PowerUps 的后端管理枚举 PowerupEffectType,为 PowerUp 的每个子类都有一个值。最终,在代码中,我需要将 PowerupEffectType 转换为 Powerup 类型(属于 class Type,通常使用 实现typeof([class name]))。

由于这是一个小组项目,我想尽可能地将 PowerupEffectType 的每个值与其对应的类 Type 结合起来,即:不只是期望我的其他程序员使用 switch 语句手动进行转换,并确保以后添加/扩展在尽可能少的地方进行尽可能少的更改。我有几个选项,到目前为止我发现的最好的方法是创建枚举伪方法,将所有内容压缩为一个 switch 语句(我想要的 99%),这要归功于我在这里找到的一些提示:http ://msdn.microsoft.com/en-us/library/bb383974.aspx

但我正试图更进一步 -我可以保存 aTypeenum我知道您可以将枚举保存为特定类型(链接:http: //msdn.microsoft.com/en-us/library/cc138362.aspx),但Type不是其中之一。当前的选择是byte、sbyte、short、ushort、int、uint、long 和 ulong。是否有任何可行的方法可以将转换 a 保存为Type上述任何数据类型并返回?

为了清楚起见,这是我希望我能做的,我正在寻找一种方法:

// (Assuming 'LightningPowerup', 'FirePowerup', and 'WaterPowerup' are
// all declared classes that inherit from a single base class)

public enum PowerupEffectType
{
    LIGHTNING = typeof(LightningPowerup),
    FIRE = typeof(FirePowerup),
    WATER = typeof(WaterPowerup)
}

有什么办法可以做到这一点,还是我只是让一个已经完成 99% 的问题的解决方案过于复杂?

提前致谢!

4

7 回答 7

93

您不能将其作为枚举的,但您可以在属性中指定它:

using System;
using System.Runtime.CompilerServices;

[AttributeUsage(AttributeTargets.Field)]
public class EffectTypeAttribute : Attribute
{
    public Type Type { get; private set; }

    public EffectTypeAttribute(Type type)
    {
        this.Type = type;
    }
}

public class LightningPowerup {}
public class FirePowerup {}
public class WaterPowerup {}

public enum PowerupEffectType
{
    [EffectType(typeof(LightningPowerup))]
    Lightning,
    [EffectType(typeof(FirePowerup))]
    Fire,
    [EffectType(typeof(WaterPowerup))]
    Water
}

然后,您可以在执行时通过反射提取这些属性值。但是,我个人只会创建一个字典:

private static Dictionary<PowerupEffectType, Type> EffectTypeMapping =
    new Dictionary<PowerupEffectType, Type>
{
    { PowerupEffectType.Lightning, typeof(LightningPowerup) },
    { PowerupEffectType.Fire, typeof(FirePowerup) },
    { PowerupEffectType.Water, typeof(WaterPowerup) }
};

无需特殊属性,无需使用繁琐的反射代码提取值。

于 2012-06-13T05:51:31.167 回答
19

这不正是你所要求的。我发现 Jon 的属性方法是最好的。但是为什么不将它包装在扩展方法中呢?

public Type GetPowerupEffectType(this PowerupEffectType powerEffect)
{
    switch (powerEffect)
    {
        case LIGHTNING:
            return typeof(LightningPowerup);
        case FIRE:
            return typeof(FirePowerup);
        case WATER:
            return typeof(WaterPowerup);
        default:
            return default(Type);
    }
}

并称之为:

PowerupEffectType e = PowerupEffectType.WATER;
var t = e.GetPowerupEffectType();
于 2012-06-13T06:09:36.923 回答
16

这样的事情怎么样?

您获得了使用枚举所做的类型安全性,以及到 Type 的隐式转换

public class PowerupEffectType
{
    private readonly Type _powerupType;

    public static implicit operator Type(PowerupEffectType powerupEffectType)
    {
        return powerupEffectType._powerupType;
    }

    private PowerupEffectType(Type powerupType)
    {
        _powerupType = powerupType;
    }

    public static readonly PowerupEffectType LIGHTNING = new PowerupEffectType(typeof(LightningPowerup));
    public static readonly PowerupEffectType FIRE = new PowerupEffectType(typeof(FirePowerup));
    public static readonly PowerupEffectType WATER = new PowerupEffectType(typeof(WaterPowerup));
}
于 2012-06-13T06:04:08.643 回答
9

你可以使用一个static Dictionary<PowerupEffectType, Powerup>. 我相信这将是你正在寻找的那种“婚姻”。它将允许轻松枚举和访问。

于 2012-06-13T05:51:57.170 回答
2

您只能使用 Microsoft 文档中的数字类型。默认情况下,枚举中每个元素的基础类型是 int。您可以使用冒号指定另一个整数类型,如前面的示例所示。有关可能类型的完整列表,请参阅枚举。参考:枚举类型

于 2012-06-13T05:45:09.393 回答
2

对不起,我不太明白这一点,你到底想达到什么目的;你能给出代码摘录吗?我不确定为什么你不能在这里只使用继承,而枚举给你的类型继承却没有。对我来说,感觉就像你在提出解决方案而不是问题,我可能完全错了,你能澄清一下你打算如何使用这些元信息吗?

我很困惑,您是在要求告诉您类型/类的实例类型的东西吗?您可以使用枚举来存储您所说的每种类型的类型列表,但您为什么要这样做呢?您说您不想让其他程序员使用 switch 语句,但是很抱歉,我看不到您将类型信息存储在...类型的某些枚举中会带来什么好处。每个实例都知道它是什么类型以及它可以做什么。

您将如何处理类型信息?如果这些类型都继承自一个基类型,那么大概它们具有可以在abstract方法中为任何特殊情况处理指定的通用功能,或者可能返回Null Object无事可做的地方(或者可能什么都不做)。这样您就不必担心添加新类 - 因为它们必须具有必要的行为。我尽量避免使用Enums,除非在您实际枚举一组固定的任意值的情况下,它们是不灵活的。 Enums 必须保持,这是非常困难的(在实践中)。

于 2012-06-13T10:17:45.723 回答
0

我实际上认为您可能想看看一个依赖注入框架。

看起来您正试图让其他开发人员在不同的组件上工作,然后您试图在最后将它们全部集成到代码库的一个中心位置。

几个项目要看:

于 2012-06-13T10:57:57.360 回答