1

我试图找出将单个键/值对属性附加到枚举的最佳方法,其中键是我的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


我通过调用以下方式 取出钥匙或MerchantId.GetStringValue().Split(","c)(0)

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


我通过调用 提取值或TransactionKey.GetStringValue().Split(","c)(1)

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

这是最有效的方法吗?代替StringValueAttribute,使用 a 创建属性怎么样,Dictionary(Of String, String)因为它是一个键/值对列表?还是字符串数组或列表?也许在 LINQ 中有什么?还是它已经尽可能高效了?

4

3 回答 3

1

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

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

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
于 2012-05-04T14:24:12.020 回答
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();
    }
}
于 2012-05-04T15:02:44.450 回答
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这是我为此示例 命名的类中扩展方法的实现:

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
于 2012-05-04T20:54:35.317 回答