1

我有一个枚举列表,如下所示:

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)

将值分配给 's 的最佳方法是什么,以便稍后enum添加's 并不意味着重新分配所有值。enum选择唯一的子系统 ID 和通知类型,应自动分配通知 ID。

例如,如果有数以千计的enum's 可能会很烦人,而我必须手动给它们编号,或者如果enum在中间添加一个则重新编号。

谢谢。

4

4 回答 4

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
于 2011-09-20T21:32:38.943 回答
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,
}
于 2011-09-20T21:10:31.117 回答
0

我猜您枚举的目的是为具有特定代码的事件命名。问题是名称和代码之间关联的规范来源是什么。如果是您(或您的代码),我看不出有任何重新编号的理由。如果它来自一些外部来源(例如文档),请尝试部署一些代码生成(例如T4 模板)。

于 2011-09-20T21:52:00.037 回答
0

如果您对杰夫的回答感到满意,那么恕我直言,设计更简洁

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但是当然,您在编译器和您可能不喜欢的编译器之间创建了依赖关系。

于 2011-09-20T22:21:03.927 回答