将单个键/值对属性附加到枚举的最佳方法是什么?

时间:2012-05-04 14:12:19

标签: asp.net vb.net dictionary enums

我正在尝试找出将单个键/值对属性附加到枚举的最佳方法,其中键是 MerchantId ,值是相应的 TransactionKey 即可。

我目前所做的是将逗号分隔的字符串放入StringValueAttribute类:

Public Enum Merchants
    <StringValue("coke,faj80785hq+faf=-1=-jfa+">
        Coke = 0
    <StringValue("pepsi,adfji=-901jnas++fdj98ua")>
        Pepsi = 1
    <StringValue("drpepper,jk878-=+9kdkdja0=a=f--daj")>
        DrPepper = 2
End Enum

Public Property Merchant As Merchants


我通过拨打.GetStringValue().Split(","c)(0)来取出密钥或 MerchantId

Public ReadOnly Property MerchantId() As String
    Get
        Return Merchant.GetStringValue().Split(","c)(0)
    End Get
End Property


我通过调用.GetStringValue().Split(","c)(1)

来提取值或 TransactionKey
Public ReadOnly Property TransactionKey() As String
    Get
        Return Merchant.GetStringValue().Split(","c)(1)
    End Get
End Property

这是最有效的方法吗?不是StringValueAttribute,而是使用Dictionary(Of String, String)创建属性,因为它是键/值对列表?或字符串数​​组或列表?也许在LINQ中的东西?或者它是否已经很有效率了?

3 个答案:

答案 0 :(得分:1)

我建议您创建自己的属性类,它以类型安全的方式获取这两个值并适当地命名它们。或者,如果不是每个项目都具有两个值,则创建两个单独的属性,每个值对应一个值。

或者更好的是,根本不要使用Enum。创建自己的类,在构造函数中获取所有三个值,然后为每个项创建一个具有共享属性的类,如下所示:

Public Class Merchants
    Public Shared ReadOnly Property Coke() As Merchant
        Get
            Return _coke
        End Get
    End Property
    Private Shared _coke = New Merchant(0, "Coke", "faj80785hq+faf=-1=-jfa+")

    ...
End Class

答案 1 :(得分:1)

您可以使用以下自定义属性和扩展方法来获取值。有些事情需要注意:

  • 它在C#中,希望没问题:)

  • 扩展方法类将MerchantIds和TransactionIds缓存在静态范围内,因此效率非常高。

  • 您通过致电(例如MerchantId获得Merchants.Coke.GetMerchantId();

  • 您通过致电(例如TransactionId获得Merchants.Coke.GetTransactionId();

此外,扩展方法不会检查传递给它们的Merchants值是否有效,因此您可以通过调用((Merchants)76282).GetMerchantId()来解除它。

[AttributeUsage(AttributeTargets.Field)]
public class MerchantDataAttribute : Attribute
{
    public MerchantDataAttribute(string merchantId, string transactionId)
    {
        this.MerchantId = merchantId;
        this.TransactionId = transactionId;
    }

    public string MerchantId
    {
        get;
        private set;
    }

    public string TransactionId
    {
        get;
        private set;
    }
}

public static class MerchantsExtensions
{
    private static readonly Dictionary<Merchants, MerchantDataAttribute> 
        _merchantsCache = CacheMerchantsCache();

    public static string GetMerchantId(this Merchants merchants)
    {
        return _merchantsCache[merchants].MerchantId;
    }

    public static string GetTransactionId(this Merchants merchants)
    {
        return _merchantsCache[merchants].TransactionId;
    }

    private static Dictionary<Merchants, MerchantDataAttribute> CacheMerchantsCache()
    {
        return Enum.GetValues(typeof(Merchants))
            .Cast<Merchants>()
            .Select(m => new
            {
                Merchant = m, 
                MerchantAttribute = GetMerchantAttribute(m)
            })
            .ToDictionary(m => m.Merchant, m => m.MerchantAttribute);
    }

    private static MerchantDataAttribute GetMerchantAttribute(Merchants merchant)
    {
        return typeof(Merchants)
            .GetMember(merchant.ToString())
            .First()
            .GetCustomAttributes(typeof(MerchantDataAttribute), inherit: false)
            .Cast<MerchantDataAttribute>()
            .First();
    }
}

答案 2 :(得分:1)

对于任何未来的访问者,我想我会发布答案的VB版本,因为那是我用这个问题标记的。此外,由于VB要求扩展在模块内部,我不得不做一些稍微不同的事情。

以下是模块:

(为了便于阅读,我使用了很多行继续。另外,为了便于阅读,我在本例中导入了SomeClass,因此我没有输入NameSpace)

Imports SomeClass

Module MerchantsExtensions

    Private ReadOnly MerchantsCache _
        As Dictionary(Of Merchants, MerchantDataAttribute) _
        = CacheMerchantsCache()

    Private Function CacheMerchantsCache() _
        As Dictionary(Of Merchants, MerchantDataAttribute)

        Return [Enum].GetValues(GetType(Merchants)) _
            .Cast(Of Merchants)() _
            .Select(Function(m) New With
            {
                .Merchant = m,
                .MerchantAttribute = GetMerchantAttribute(m)
            }) _
            .ToDictionary(Function(m) m.Merchant, _
                          Function(m) m.MerchantAttribute)

    End Function

    Private Function GetMerchantAttribute(merchant As Merchants) _
        As MerchantDataAttribute

        Return GetType(Merchants) _
            .GetMember(merchant.ToString()) _
            .First() _
            .GetCustomAttributes(GetType(MerchantDataAttribute), _
                                 inherit:=False) _
            .Cast(Of MerchantDataAttribute)() _
            .First()

    End Function

    <Runtime.CompilerServices.Extension()>
    Public Function GetMerchantId(merchants As Merchants) As String

        Return MerchantsCache(merchants).Id

    End Function

    <Runtime.CompilerServices.Extension()>
    Public Function GetTransactionKey(merchants As Merchants) As String

        Return MerchantsCache(merchants).TransactionKey

    End Function

End Module


以下是此示例中名为SomeClass的类I中的扩展方法的实现:

Public Class SomeClass

    Public Enum Merchants
        <MerchantData("coke", "faj80785hq+faf=-1=-jfa+")>
            Coke = 0
        <MerchantData("pepsi","adfji=-901jnas++fdj98ua")>
            Pepsi = 1
        <MerchantData("drpepper","jk878-=+9kdkdja0=a=f--daj")>
            DrPepper = 2
    End Enum

    <AttributeUsage(AttributeTargets.Field)>
    Public Class MerchantDataAttribute : Inherits Attribute

        Public Sub New(merchantId As String, transactionKey As String)
            _Id = merchantId
            _TransactionKey = transactionKey
        End Sub

        Public Property Id() As String
        Public Property TransactionKey() As String

    End Class

End Class