枚举结构?一个行为类似Enum的Value对象

时间:2008-11-28 11:12:15

标签: c# enums

我想知道你将如何解决这个问题

我有两种税收可以适用于我的产品。我特别希望避免将Taxrates持久存储到数据库中,同时仍然可以在中心位置更改它们(例如20%到19%的Taxrate等)。

所以我决定将它们编译到我的应用程序中是很好的(它是内部的)。问题是我不仅要知道税率,还要知道税率的名称。

我可以使用映射到该值的枚举。但是我必须创建一些方法来检索英语枚举值的该Taxrate的德语名称(我用英语写代码,App是德语)。

我想过只使用硬编码对象来反映这一点,

public interface Taxrate
{
    string Name { get; }
    decimal Rate { get; }
}

public class NormalTaxRate : Taxrate
{
    public string Name
    { get { return "Regelsteuersatz"; } }

    public decimal Rate
    { get { return 20m; } }
}

但是我必须创建一些包含这两个对象的两个实例的列表。静态地做它可能有用,但我仍然需要保留某种列表。 此外,我必须找到一种方法将我的POCO域对象映射到此,因为我怀疑NHibernate可以根据字段中的值实例化正确的对象。

感觉不对,我觉得我在这里遗漏了一些东西。希望有人有更好的解决方案,我想不出一个。

问候,丹尼尔

Ps:如果你找到合适的东西,也请重新提出这个问题,我现在想不出更有意义的标签。

5 个答案:

答案 0 :(得分:6)

编辑:请注意,此处的代码可以通过私有构造函数来获取税率和名称来轻松缩写。我假设在现实生活中,税率之间可能存在实际的行为差异。

听起来你想要像Java的枚举一样。

C#使得它相当棘手,但你可以在某种程度上使用私有构造函数和嵌套类来完成它:

 public abstract class TaxRate
 {
     public static readonly TaxRate Normal = new NormalTaxRate();
     public static readonly TaxRate Whatever = new OtherTaxRate();

     // Only allow nested classes to derive from this - and we trust those!
     private TaxRate() {}

     public abstract string Name { get; }
     public abstract decimal Rate { get; }

     private class NormalTaxRate : TaxRate
     {
         public override string Name { get { return "Regelsteuersatz"; } }
         public override decimal Rate { get { return 20m; } }
     }

     private class OtherTaxRate : TaxRate
     {
         public override string Name { get { return "Something else"; } }
         public override decimal Rate { get { return 120m; } }
     }
 }

你可能想在TaxRate中使用某种静态方法来根据名称或其他方式返回正确的实例。

我不知道这与NHibernate相比有多么容易,但希望它在某种程度上会有所帮助......

正如评论中所指出的那样,它非常难看 - 或者当你有很多不同的价值观时,至少可以变得非常难看。部分课程可以在这里提供帮助:

// TaxRate.cs
public partial abstract class TaxRate
{
    // All the stuff apart from the nested classes
}

// TaxRate.Normal.cs
public partial abstract class TaxRate
{
    private class NormalTaxRate : TaxRate
    {
        public override string Name { get { return "Regelsteuersatz"; } }
        public override decimal Rate { get { return 20m; } }
    }
}

// TaxRate.Other.cs
public partial abstract class TaxRate
{
    private class OtherTaxRate : TaxRate
    {
        public override string Name { get { return "Something else"; } }
        public override decimal Rate { get { return 120m; } }
    }
}

然后,您可以使用项目文件来显示嵌套类作为外部类的子项,如this SO question所示。

答案 1 :(得分:3)

我会这样做:

public class TaxRate
{
    public readonly string Name;
    public readonly decimal Rate;

    private TaxRate(string name, decimal rate)
    {
        this.Name = name;
        this.Rate = rate;
    }


    public static readonly TaxRate NormalRate = new TaxRate("Normal rate", 20);
    public static readonly TaxRate HighRate = new TaxRate("High rate", 80);
}

这样很容易使用它 - 只需访问TaxRate静态成员,如枚举值。要将它与NHibernate一起使用,您将必须创建自己的自定义NHibernate类型类(请参阅相关文档),但这并不是那么难。我已经做过一次了。

答案 2 :(得分:1)

为什么不在应用程序配置中存储税率,例如在web.config或app.config文件中?这些是简单的XML文件,其中有一个部分,您可以在其中使用键和值指定自定义参数。例如:

<appSettings>
    <add key="BaseTaxRate" value=20"/>
    <add key="HigherTaxRate" value=40"/>
</appSettings>

然后您可以在应用程序中简单地检索这些:

string baseTaxRate = ConfigurationSettings.AppSettings["BaseTaxRate"];

这样,它们很容易更改,不需要重新编译和重新部署您的应用程序。

显然,您还可以将税率的名称存储为配置文件中的额外设置。

答案 3 :(得分:1)

我必须说我发现使用嵌套类的想法有点奇怪,因为在我看来这是主流要求。

将速率存储在数据库(或其他持久性介质,如应用程序配置文件)中有什么问题?我原本以为你想为每种税率都有一个唯一的Id,用于产品和税率之间的关系。

所以你会有一个带有Id / Description / Rate(*)的TaxRate类。您可以加载包含所有可能值的字典,以便通过Id快速查找费率/说明。

(*)在多语言应用中,您需要查找每对Culture / Id的本地化描述 - 从数据库中的第二个表或资源等...

无论如何,硬连线率似乎是错误的 - 特别是现在政府正在试行税率以试图提振经济。

答案 4 :(得分:1)

我知道这是违背你的问题的主要前提,但我想对这个问题给出一些想法。

虽然现在似乎是一个合理的决定,以避免在数据库中持续增值税和税率,但时间会证明你错了。首先,您应始终能够在给定时间提取数据,为此,您需要对费率进行版本控制。

众所周知,唯一不变的是变化。说费率变化(他们会)。如果您丢失了对源的访问权限,则无法进行适当的维护。如果将税率从固定增值税分为不同税率,则更新系统将更加困难。

这个问题不是起来的问题。截至12月1日,英国已将增值税从17.5%降至15%。许多人坚持使用旧软件而无法更新费率。请避免犯这个错误(将费率分成数据库也会带来很多其他改进)。