管理常量列表

时间:2014-05-25 17:09:42

标签: c#

在几个项目中,我们在数据库中有一个常量值列表。每个都有一个表,名称和GUID值。例如,故障单状态表可能有3个值,“打开”,“已关闭”和“保持”。在我们的C#代码中,框架生成一个C#文件,如下所示。

public class TicketStatus { 
     public static Guid Open =  new Guid( "7ae15a71-6514-4559-8ea6-06b9ddc7a59a");
     public static Guid Closed =  new Guid( "41f81283-57f9-4bda-a03c-f632bd4d1628");
     public static Guid Hold =  new Guid( "41bcc323-258f-4e58-95be-e995a78d2ca8");
}; // end of TicketStatus

这允许我们编写一些干净的(ish)代码来设置故障单状态,如下所示 ticket.strStatus = TicketStatus.Open.ToString();

虽然这有效: - 它生成非常干净的C#代码,易于准备和维护 - 它受Intellisense支持

在那,它仍然很笨拙 - 我们必须不断转换为字符串以进行许多操作 - 使用GUID似乎有点矫枉过正。 - 我们不能写一个“正常”的开关​​语句

// This won't compile
        switch( strStatus ) {
        case TicketStatus.Open:
        case TicketStatus.Closed:
        // do some stuff.
        break;
        }

代码最初是用一堆GUID实现的,用于管理数据库以全部大写形式返回值的情况。

问题:对这些常量值进行编码的最佳方法是什么,以便它支持IntelliSense和switch语句?

4 个答案:

答案 0 :(得分:2)

谢谢Kirk, 这是我正在使用的字符串解决方案。

public static class TicketStatus {
    public const string Open = "7ae15a71-6514-4559-8ea6-06b9ddc7a59a";
    public const string Closed = "41f81283-57f9-4bda-a03c-f632bd4d1628";
    public const string Hold = "41bcc323-258f-4e58-95be-e995a78d2ca8";
}; // end of TicketStatus

string strTemp = TicketStatus.Open;
switch (strTemp) {
    case TicketStatus.Open:
        strTemp = "Jackpot";
        break;
}

答案 1 :(得分:1)

序言

我确实认为,你应该尽可能坚持这一点。

public static class TicketStatus {
    public const string Open = "7ae15a71-6514-4559-8ea6-06b9ddc7a59a";
    public const string Closed = "41f81283-57f9-4bda-a03c-f632bd4d1628";
    public const string Hold = "41bcc323-258f-4e58-95be-e995a78d2ca8";
}; // end of TicketStatus

如果你想要一些魔法:)

有一个解决方案,没有人在这里提到过。您可以使用属性将自定义值分配给枚举。您需要定义一个属性和一些辅助类:

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

    public GuidValue(Guid guid)
    {
        this.Guid = guid;
    }

    public GuidValue(string stringGuid)
    {
        this.Guid = new Guid(stringGuid);
    }
}

public static class GuidBackedEnums
{
    private static Guid GetGuid(Type type, string name)
    {
        return type.GetField(name).GetCustomAttribute<GuidValue>().Guid;
    }

    public static Guid GetGuid(Enum enumValue)
    {
        Type type = enumValue.GetType();
        if (!type.IsEnum)
            throw new Exception();
        return GetGuid(type, enumValue.ToString());
    }

    public static T CreateFromGuid<T>(Guid guid)
    {
        Type type = typeof(T);
        if (!type.IsEnum)
            throw new Exception();
        foreach (var value in Enum.GetValues(type))
        {
            if (guid == GetGuid(type, value.ToString()))
                return (T)value;
        }
        throw new Exception();
    }
}

然后您可以通过以下方式使用它:

enum TicketStatus
{
    [GuidValue("7ae15a71-6514-4559-8ea6-06b9ddc7a59a")]
    Open,
    [GuidValue("41f81283-57f9-4bda-a03c-f632bd4d1628")]
    Closed,
    [GuidValue("41bcc323-258f-4e58-95be-e995a78d2ca8")]
    Hold
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(GuidBackedEnums.CreateFromGuid<TicketStatus>(new Guid("41f81283-57f9-4bda-a03c-f632bd4d1628")));
        Console.WriteLine(GuidBackedEnums.GetGuid(TicketStatus.Hold));
    }
}

当然,TicketStatus是一个普通的枚举。所以你可以在switch语句中使用它。

答案 2 :(得分:0)

试试这个

public static Guid Open = new Guid("7ae15a71-6514-4559-8ea6-06b9ddc7a59a");
        public static Guid Closed = new Guid("41f81283-57f9-4bda-a03c-f632bd4d1628");
        public static Guid Hold = new Guid("41bcc323-258f-4e58-95be-e995a78d2ca8");
        public enum Status1
        {
             Open,
             Close,
            Hold
        }
        public static Dictionary<Guid, Status1> Dic = new Dictionary<Guid, Status1>()
        {
            {Open , Status1.Open},
            {Closed , Status1.Close},
            {Hold , Status1.Hold}
        };  

然后

var a = TicketStatus.Closed;
var label = TicketStatus.Dic.FirstOrDefault(e => e.Key == a).Value;
switch (label)
{
    case TicketStatus.Status1.Close:

}

让您的代码更具可读性

答案 3 :(得分:0)

我会使用类似java的枚举和一些反射。这是一个C#实现示例。我不能使用开关,但它会很快为您确定所需的对象。

using System;
using System.Reflection;
using System.Linq;

public class TicketStatus
{
    private string _guid;

    private TicketStatus(string guid)
    {
        _guid = guid;
    }

    public string GuidValue {get {return _guid; } }

    public static readonly TicketStatus Open =  new TicketStatus("7ae15a71-6514-4559-8ea6-06b9ddc7a59a");
    public static readonly TicketStatus Closed =  new TicketStatus("41f81283-57f9-4bda-a03c-f632bd4d1628");
    public static readonly TicketStatus Hold =  new TicketStatus("41bcc323-258f-4e58-95be-e995a78d2ca8");

    //Reads all static readonly fields and selects the one who has the specified GUID
    public static TicketStatus Identify(string guid)
    {
        var ticket = typeof(TicketStatus).GetFields()
                     .Where(x => (x.IsStatic == true) && (x.IsInitOnly == true) )
                     .Select(x => x.GetValue(null))
                     .SingleOrDefault(x => (x as TicketStatus).GuidValue == guid)
                     as TicketStatus;
        return ticket;

    }
}

public class Program
{
    public static void Main()
    {   
        var guid = "7ae15a71-6514-4559-8ea6-06b9ddc7a59a";
        var ticket = TicketStatus.Identify(guid);
        if(ticket != null)
        {
            Console.WriteLine(ticket.GuidValue + " found");
        }
        else
        {
            Console.WriteLine("unknown ticket");
        }
    }
}