2011-09-20 25 views
1

我有枚舉的列表如下:用枚舉和HEX很好的工作值

public enum EventID : uint 
{ 
    SAMPLE_EVENT_1 = 0xDCCA0000, 
    SAMPLE_EVENT_2 = 0xDCCB0001, 
    SAMPLE_EVENT_3 = 0xDCCA0002, 
    SAMPLE_EVENT_4 = 0xDCC00003, 
    SAMPLE_EVENT_5 = 0xDCCA0004, 
    ... 
} 

每個枚舉的十六進制值如下破譯:

/// DCC X XXXX 
/// --- - ---- 
/// | | |--> Notification ID (0x0000 to 0xFFFF) 
/// | |-----> Notification Type (0x0 to 0xA) 
/// |--------> Sub-system ID (0xDCC) 

什麼是最好的方式將值分配給enum's,以便稍後添加enum並不意味着重新分配所有值。唯一的子系統ID和通知類型被選中,通知ID應該被自動分配。

例如,如果有成千上萬的enum,我不得不手動編號或重新編號,如果在中間添加enum可能會很煩人。

謝謝。

+0

你有這麼大的枚舉的動機是什麼?我有強烈的感覺,你濫用枚舉的方式,他們不是爲了設計。 –

+0

@JakubŠturc它們用於表示事件的另一個子系統,例如硬件事件或數據更改。 –

回答

3

如果你問我,你不應該在編碼您的枚舉值這個數據。如果能夠獲得這些信息,最好應用它們的屬性。讓枚舉的實際值代表NotificationId以獲取自動分配的值。

[AttributeUsage(AttributeTargets.Field, AllowMultiple=false)] 
public class SubsystemIdAttribute : Attribute 
{ 
    public SubsystemIdAttribute(ushort value) 
    { 
     this.Value = (ushort)(value & 0xFFF); 
    } 

    public ushort Value { get; private set; } 
} 

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] 
public class NotificationTypeAttribute : Attribute 
{ 
    public NotificationTypeAttribute(byte value) 
    { 
     this.Value = (byte)(value & 0xF); 
    } 

    public byte Value { get; private set; } 
} 

public enum EventId 
{ 
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_1, 
    [SubsystemId(0xDCC)] [NotificationType(0xB)] SAMPLE_EVENT_2, 
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_3, 
    [SubsystemId(0xDCC)] [NotificationType(0x0)] SAMPLE_EVENT_4, 
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_5, 
} 

public static class EventIdExtensions 
{ 
    public static ushort GetSubsystemId(this EventId eventId) 
    { 
     return GetAttributeValue(eventId, (SubsystemIdAttribute a) => a.Value); 
    } 

    public static byte GetNotificationType(this EventId eventId) 
    { 
     return GetAttributeValue(eventId, (NotificationTypeAttribute a) => a.Value); 
    } 

    private static TValue GetAttributeValue<TAttribute, TValue>(EventId eventId, Func<TAttribute, TValue> selector) 
     where TAttribute : Attribute 
    { 
     return typeof(EventId).GetField(eventId.ToString()) 
      .GetCustomAttributes(false) 
      .OfType<TAttribute>() 
      .Select(selector) 
      .Single(); 
    } 
} 

要獲得屬性的值,調用相應的擴展方法。

var eventId = EventId.SAMPLE_EVENT_3; 
var subsystemId = eventId.GetSubsystemId();   // 0xDCC 
var notificationType = eventId.GetNotificationType(); // 0xA 
+0

我真的很喜歡使用屬性的想法,雖然我不是很熟悉它們。是否有可能爲每個枚舉有兩個屬性,一個用於子系統ID,另一個用於通知類型?這樣通知ID就會自動增加。如果可能的話,你可以編輯你的答案來表明這是如何完成的? –

+0

是的,當然。這實際上會更清潔恕我直言(更加詳細)。讓我做出必要的改變。 –

+0

另外,如何獲取枚舉的屬性值?例如要打印。 –

0

枚舉只能自動遞增1,因此您必須按子系統順序保留它們,然後通知類型,然後通知ID,並且只有當您分配了缺口時。因此,爲了維持秩序正確,你的上面枚舉應該是這樣:

public enum EventID : uint 
{ 
    SAMPLE_EVENT_1 = 0xDCCA0000, 
    SAMPLE_EVENT_3 = 0xDCCA0002, 
    SAMPLE_EVENT_5 = 0xDCCA0004, 
    SAMPLE_EVENT_2 = 0xDCCB0001, 
    SAMPLE_EVENT_4 = 0xDCC00003, 
} 
0

我猜你的枚舉的這個目的是給一個名稱與特定代碼的事件。問題是名稱和代碼之間的典型聯繫來源是什麼。如果是你(或你的代碼),我沒有看到任何重新編號的理由。如果它來自某些外部來源(例如文檔),則嘗試部署一些代碼生成(例如T4 templates)。

0

如果你很高興與Jeff's answer這是恕我直言,更清潔的設計

public class EventId 
{ 
    public static readonly SAMPLE_EVENT_1 = new EventId(0xDCC, 0xA); 
    public static readonly SAMPLE_EVENT_2 = new EventId(0xDCC, 0xA); 
    public static readonly SAMPLE_EVENT_3 = new EventId(0xDCC, 0xA); 
    public static readonly SAMPLE_EVENT_4 = new EventId(0xDCC, 0xA); 

    public readonly ushort SubSystemId; 
    public readonly byte NotificationType; 
    public readonly ushort NotificationId; 

    private static ushort notificationCounter = 0; 

    private EventId(ushort subSystemId, byte notificationType) 
    { 
     this.SubSystemId = subSystemId; 
     this.NotificationType= notificationType; 
     this.NotificationId = notificationCounter++; 
    } 
} 

當然你創建編譯器和NotificationId,你可能不喜歡之間的依賴關係。