2009-07-08 54 views
24

由于枚举使用整数,我可以用什么样的结构,给我挂的名称值枚举类访问:枚举与字符串以外的返回类型?

[我知道这是不对的,寻找替代]

private enum Project 
    { 
     Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"), 
     Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2"), 
     Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1"), 
     Sales = new Guid("A5690E7-1111-4AFB-B44D-1DF3AD66D435"), 
     Replacement = new Guid("11E5CBA2-EDDE-4ECA-BDFD-63BDBA725C8C"), 
     Modem = new Guid("6F686C73-504B-111-9A0B-850C26FDB25F"), 
     Audit = new Guid("30558C7-66D9-4189-9BD9-2B87D11190"), 
     Queries = new Guid("9985242-516A-4151-B7DD-851112F562") 
    } 

编辑2014年7月20日

这是一个较新的回答这个问题。使用Attribute类和辅助方法,定义您的枚举所需的额外属性。

public enum MultiValueEnum 
    { 
     [FooAttribute("alpha", 20d, true)] 
     First, 
     [FooAttribute("beta", 40.91d, false)] 
     Second, 
     [FooAttribute("gamma", 1.2d, false)] 
     Third, 
    }  

    public class FooAttribute : Attribute 
      { 
       internal FooAttribute(string name, double percentage, bool isGood) 
       { 
        this.Name = name; 
        this.Percentage = (decimal)percentage; 
        this.IsGood = isGood; 
       } 
       public string Name { get; private set; } 
       public decimal Percentage { get; private set; } 
       public bool IsGood { get; private set; } 
      } 



    public static TAttribute GetAttribute<TAttribute>(this Enum value) 
     where TAttribute : Attribute 
     { 
      var type = value.GetType(); 
      var name = Enum.GetName(type, value); 
      return type.GetField(name) 
       .GetCustomAttributes(false) 
       .OfType<TAttribute>() 
       .SingleOrDefault(); 
     } 

这使得它如此简单:

 MultiValueEnum enumVar = MultiValueEnum.First; 
     var enumStringValue = enumVar.GetAttribute<FooAttribute>().Name; 
     var enumValueDecimal = enumVar.GetAttribute<FooAttribute>().Percentage; 
     var enumBool = enumVar.GetAttribute<FooAttribute>().IsGood; 

回答

22

否则,您可以为您的枚举创建自定义属性,该属性可以容纳Guid。

旁边的东西这些行:

class EnumGuid : Attribute 
{ 
    public Guid Guid; 

    public EnumGuid(string guid) 
    { 
     Guid = new Guid(guid); 
    } 
} 

而且你再使用它像这样:

enum Project 
{ 
    [EnumGuid("2ED3164-BB48-499B-86C4-A2B1114BF1")] 
    Cleanup = 1, 
    [EnumGuid("39D31D4-28EC-4832-827B-A11129EB2")] 
    Maintenance = 2 
    // and so forth, notice the integer value isn't supposed to be used, 
    // it's merely there because not assigning any value is a performance overhead. 
} 

最后,你可以(我总是这样做),用于方便地获得创建扩展GUID:

static Guid GetEnumGuid(this Enum e) 
{ 
    Type type = e.GetType(); 

    MemberInfo[] memInfo = type.GetMember(e.ToString()); 

    if (memInfo != null && memInfo.Length > 0) 
    { 
     object[] attrs = memInfo[0].GetCustomAttributes(typeof(EnumGuid),false); 
     if (attrs != null && attrs.Length > 0) 
      return ((EnumGuid)attrs[0]).Guid; 
    } 

    throw new ArgumentException("Enum " + e.ToString() + " has no EnumGuid defined!"); 
} 

所以最终你必须与你的枚举是:

Guid guid = Project.Cleanup.GetEnumGuid(); 

我使用这种方法来将说明附加到枚举上,通常是包含空格的较长字符串,因此不能用作名称。

11

我见过使用亚音速存储列和表名这种方法(结构)。

internal struct Project 
{ 
    public static Guid Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"); 
    public static Guid Maintenance = new Guid("39D31D4-28EC-4832-827B-A129EB2"); 
    public static Guid Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1"); 
    public static Guid Sales = new Guid("A5690E7-1111-4AFB-B44D-1DF3AD66D435"); 
    public static Guid Replacement = new Guid("11E5CBA2-EDDE-4ECA-BD63-B725C8C"); 
    public static Guid Modem = new Guid("6F686C73-504B-111-9A0B-850C26FDB25F"); 
    public static Guid Audit = new Guid("30558C7-66D9-4189-9BD9-2B87D11190"); 
    public static Guid Queries = new Guid("9985242-516A-4151-B7DD-851112F562"); 
} 

编辑: - 感谢评论代码中的缺陷。首先,如果Guid字符串不是无效的,它将被编译。至于不创建实例访问的变量是他们需要公共静态

+1

无法访问结构中的专用字段,也无法像在结构中那样初始化字段。 – leppie 2009-07-08 11:01:28

+3

他们需要也是静态的,例如工作。 – leppie 2009-07-08 11:02:09

+0

你不应该能够创建这个结构体的实例,因为它只能作为一个容器来使用 – 2009-07-08 11:05:03

0

当这样的问题,我用结构与consts作为公共成员面临:

public struct FileExtensions 
{ 
    public const string ProcessingExtension = ".lck"; 
    public const string ProcessedExtension = ".xml"; 
    public const string FailedExtension = ".failed"; 
    public const string CsvExtension = ".csv"; 
} 
0

您可以创建一个静态类只包含常量值。 例如:

internal static class Project 
{ 
    public static readonly Guid Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"); 
    public static readonly Guid Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2"); 
    public static readonly Guid Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1"); 
} 

这样,类作用简称为容器和对象不能从它创建。

在VB中,这将是一个模块:

Friend Module Project 
    Public Shared ReadOnly Cleanup As Guid = New Guid("2ED3164-BB48-499B-86C4-A2B1114BF1") 
    Public Shared ReadOnly Maintenance As Guid = New Guid("39D31D4-28EC-4832-827B-A11129EB2") 
    Public Shared ReadOnly Upgrade As Guid = New Guid("892F865-E38D-46D7-809A-49510111C1") 
End Module 
0

枚举类型可以only supportintegral types作为其值(除炭)。然而,你可以使用像Dictionary这样的名称来查找一个值。

Dictionary<Guid> lookup = new Dictionary<Guid>(); 
lookup["Cleanup"] = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"); 
lookup["Maintenance"] = new Guid("39D31D4-28EC-4832-827B-A11129EB2"); 
lookup["Upgrade"] = new Guid("892F865-E38D-46D7-809A-49510111C1"); 
// etc... 

另一种选择是在静态类中有一系列只读值。

public static class Guids 
{ 
    public static readonly Guid Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"), 
    public static readonly Guid Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2"), 
    public static readonly Guid Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1"), 
} 
5

我可能会去这个词典路线。基本上有一个查找表:

public class GuidMapper 
{ 
    private Dictionary<GuidTypes, Guid> mGuidMap = new Dictionary<GuidTypes, Guid>(); 
    public enum GuidTypes: int 
    { 
     Cleanup, 
     Maintenance, 
     Upgrade, 
     Sales, 
     Replacement, 
     Modem, 
     Audit, 
     Queries 
    } 

    public GuidMapper() 
    { 
     mGuidMap.Add(GuidTypes.Cleanup, new Guid("2ED31640-BB48-499B-86C4-A2B1114BF100")); 
     mGuidMap.Add(GuidTypes.Maintenance, new Guid("39D31D40-28EC-4832-827B-A11129EB2000")); 
     mGuidMap.Add(GuidTypes.Upgrade, new Guid("892F8650-E38D-46D7-809A-49510111C100")); 
     mGuidMap.Add(GuidTypes.Sales, new Guid("A5690E70-1111-4AFB-B44D-1DF3AD66D435")); 
     mGuidMap.Add(GuidTypes.Replacement, new Guid("11E5CBA2-EDDE-4ECA-BDFD-63BDBA725C8C")); 
     mGuidMap.Add(GuidTypes.Modem, new Guid("6F686C73-504B-1110-9A0B-850C26FDB25F")); 
     mGuidMap.Add(GuidTypes.Audit, new Guid("30558C70-66D9-4189-9BD9-2B87D1119000")); 
     mGuidMap.Add(GuidTypes.Queries, new Guid("99852420-516A-4151-B7DD-851112F56200")); 
    } 

    public Guid GetGuid(GuidTypes guidType) 
    { 
     if (mGuidMap.ContainsKey(guidType)) 
     { 
      return mGuidMap[guidType]; 
     } 
     return Guid.Empty; 
    } 
} 
2

如果您需要正确的enum式的语义和类型安全的,那么你可以使用这样的模式。

(你可以进一步充实它,如果你需要像转换操作符,GetUnderlyingTypeToString等演员如果你想重新使用该模式为多enum般的班级,不同的基础类型,那么你可以将任何普通的代码到一个通用抽象基类)

Project x = Project.Cleanup; 
Project y = Project.Cleanup; 
Project z = Project.Maintenance; 

Console.WriteLine(x == y);  // True 
Console.WriteLine(x == z);  // False 
Console.WriteLine(x.Value); // 47801daa-7437-4bfe-a240-9f7c583018a4 

// this line will cause a compiler error 
Console.WriteLine(x == new Guid("47801daa-7437-4bfe-a240-9f7c583018a4")); 

// ... 

public class Project 
{ 
    private Project(Guid v) { Value = v; } 
    public Guid Value { get; private set; } 

    public static readonly Project Cleanup = 
     new Project(new Guid("47801daa-7437-4bfe-a240-9f7c583018a4")); 

    public static readonly Project Maintenence = 
     new Project(new Guid("2548a7f3-7bf4-4533-a6c1-dcbcfcdc26a5")); 

    public static readonly Project Upgrade = 
     new Project(new Guid("ed3c3e73-8e6a-4c09-84ae-7f0876d194aa")); 
}