是否可以使用枚举动态获取静态类?

时间:2016-01-25 18:06:49

标签: c# unity3d

我想使用静态类为我的应用程序创建配置。

首先请原谅我的无知,我不是全职的c#dev。我来自Ruby / Javascript世界,其中动态访问常量和&变量很简单。

这是否是正确的方法我现在不是百分之百。会很高兴其他建议的方法。

我的配置有以下静态类设置:

public static class Config
{
    public static class MaterialQuality
    {
        public static class Low
        {
            public const float Value = 0.1f;
            public const int Cost = 10;
        }

        public static class Medium
        {
            public const float Value = 0.2f;
            public const int Cost = 20;
        }

        public static class High
        {
            public const float Value = 0.2f;
            public const int Cost = 40; 
        }
    }
}

然后我有一个类Material,它传递一个与上述类型Low,Medium,High相关的枚举值。 enum统一的原因为开发人员提供了一种快速方法,可以为关卡设计人员提供一个对象的选项列表。

因此,通过选择枚举值,关卡设计人员可以设置存储在配置中的属性,而无需直接在对象上输入值。初始化时,将针对对象设置值。

在构造函数中,我想为Cost&设置成员变量。来自Value枚举值的静态配置值的MaterialQuality

public enum MaterialQuality
{
    Low,Medium,High 
}

public class Material
{
    private int Cost;
    private float Value;

    Material(MaterialQuality quality) {

        Cost = Config.MaterialQuality.<quality>.Cost;
        Value = Config.MaterialQuality.<quality>.Value;

        //in Javascript I'd use associative array access to the object
        Cost = Config.MaterialQuality[quality].Cost;

        //in Ruby we have const_get() on classes.
        Cost = Config.MaterialQuality.const_get(quality).Cost

    }

}

这种方法的主要原因是为配置和提供单一的位置。为非技术人员提供一种相当简单的方法来更改应用程序的各个部分,而无需深入研究主要类。它还允许我利用intellisense中可用的常量。

6 个答案:

答案 0 :(得分:2)

我喜欢使用字典进行此类配置。

void Main()
{
    var config = Config.Qualities[MaterialQualities.Low];
    var cost = config.Cost;
    var value = config.Value;
}

public static class Config
{
    public static Dictionary<MaterialQualities, MaterialQuality> Qualities =
        new Dictionary<MaterialQualities, MaterialQuality>
        {
            { MaterialQualities.Low, new MaterialQuality { Value = 0.1F, Cost = 10 }},
            { MaterialQualities.Medium, new MaterialQuality { Value = 0.2F, Cost = 20 }}, 
            { MaterialQualities.High, new MaterialQuality { Value = 0.2F, Cost = 40 }},
        };  
}

public class MaterialQuality
{
    public float Value { get; set; }
    public int Cost { get; set; }
}

public enum MaterialQualities
{
    Low, Medium, High
}

答案 1 :(得分:1)

可能更好的方法是:

public static class Config
{
    public class Material
    {
        public Material(float value, int cost){
            Value = value;
            Cost = cost;
        }

        public float Value {get; private set;}
        public int Cost {get; private set;}

        public Material GetFor(MaterialQuality quality){
             switch(quality){
                 case MaterialQuality.Low: return new Material(0.1f, 10);
                 case MaterialQuality.Medium: return new Material(0.2f, 20);
                 case MaterialQuality.High: return new Material(0.2f, 40);
             }
             throw new Exception("Unknown material quality " + quality);
        }

    }
}

以后你可以使用它:

    //....
    Material materialData = Material.GetFor(quality);
    Cost = materialData.Cost;
    Value = materialData.Value;
    //...

答案 2 :(得分:1)

我会在MaterialQuantity中使用struct和static属性而不是enum。如下所示:

public struct MaterialQualityInfo
{
    public MaterialQualityInfo( float value, int cost )
    {
        Value = value;
        Cost = cost;
    }

    public float Value { get; private set; }
    public int Cost { get; private set; }
}

public static class Config
{
    public static class MaterialQuality
    {
        public static MaterialQualityInfo Low
        {
            get { return new MaterialQualityInfo( 0.1f, 10 ); }
        }

        public static MaterialQualityInfo Medium
        {
            get { return new MaterialQualityInfo( 0.2f, 20 ); }
        }

        public static MaterialQualityInfo High
        {
            get { return new MaterialQualityInfo( 0.2f, 40 ); }
        }
    }
}

public class Material
{
    private int Cost;
    private float Value;

    Material( MaterialQualityInfo quality )
    {

        Cost = quality.Cost;
        Value = quality.Value;

    }
}

答案 3 :(得分:1)

恕我直言,这不是静态类的好用法。您应该使用常规的面向对象编程来解决问题。

我发现所有材质都有2个共同属性:ValueCost。对我来说,这意味着你应该设计一个名为MaterialQuality的类:

public class MaterialQuality
{
     public float Value { get; set; }
     public int Cost { get; set; }
}

如果材质是应用程序配置的一部分,我发现您应该按如下方式设计Configuration类:

public class Configuration
{
    public List<MaterialQuality> MaterialQualities { get; } = new List<MaterialQuality>();
}

...如果您想按应用程序生命周期初始化配置,可以使用静态字段初始化程序改进Configuration类:

public class Configuration
{
    private readonly static Configuration _current = new Configuration();

    public static Configuration Current => _current;

    public List<MaterialQuality> MaterialQualities { get; } = new List<MaterialQuality>();
}

现在,将新材料质量添加到当前配置就像下面的代码一样简单:

Configuration.Current.MaterialQualities.Add(new MaterialQualities { Value = 0.1f, Cost = 10 });

如果您想提供一个流畅的API来添加材料质量也很容易:我们将公共MaterialQualities属性转换为ImmutableList<T>,因此您强制开发人员使用方法添加材料)并添加AddMaterial方法:

public class Configuration
{
    private readonly static Configuration _current = new Configuration();
    private readonly List<MaterialQuality> _materialQualities = new List<MaterialQuality>();

    public static Configuration Current => _current;

    public IImmutableList<MaterialQuality> MaterialQualities => _materialQualities.ToImmutableList();

    public Configuration AddMaterial(float value, int cost)
    {
         _materialQualities.Add(new MaterialQuality { Value = value, Cost = cost });

         return this;
    }
}

...现在添加许多材料会更好看!

Configuration.Current.AddMaterial(0.1f, 10)
                     .AddMaterial(0.2f, 20)
                     .AddMaterial(0.2f, 40);

答案 4 :(得分:0)

怎么样:

public enum MaterialQuality
{
    Low, Medium, High
}

public class Material
{
    private int Cost;
    private float Value;
    private readonly Dictionary<MaterialQuality, Tuple<int, float>> storageMap = new Dictionary<MaterialQuality, Tuple<int, float>>
    {
        { MaterialQuality.Low, Tuple.Create(10, 0.1f)},
        { MaterialQuality.Low, Tuple.Create(20, 0.2f)},
        { MaterialQuality.Low, Tuple.Create(40, 0.2f)},
    }; 

    public Material(MaterialQuality quality)
    {

        Cost = storageMap[quality].Item1;
        Value = storageMap[quality].Item2;
    }

}

答案 5 :(得分:0)

如果你没有广泛使用你的枚举,你可以做类似的事情:

public class Material
{
   public float Value { get; private set; }
   public int Cost { get; private set; }
   public Material(float value, int cost)
   {
     Value = value;
     Cost = cost;
   }
   public static Material Low { get { return new Material(0.1f, 10); } }
   public static Material Medium { get { return new Material(0.2f, 20); } }
   public static Material High { get { return new Material(0.2f, 40); } }
}

然后:

var myLowMaterial = Material.Low;
var myMediumMaterial = Material.Medium;
var myHighMaterial = Material.High;

除非您使用enum作为某些内容,否则您可以添加:

 public static Material Get(MaterialQuality quality)
 {
   switch(quality)
   {
     case MaterialQuality.Low: 
        return Low;
     case MaterialQuality.Medium: 
        return Medium;
     case MaterialQuality.High: 
        return High;
   }
   throw new Exception("We should never go here");
}