【问题标题】:VB.NET: Get dynamically value of constantsVB.NET:动态获取常量值
【发布时间】:2013-04-08 12:40:18
【问题描述】:

如果有以下常量定义:

Protected Const Xsl As String = "Configuration.Xsl"
Protected Const Form As String = "Settings.Form"
Protected Const Ascx As String = "Implementation.Ascx"
...

为了填充字典,我使用这个常量作为键:

MyDictionary.Add(Converter.Xsl, "Item 1")
MyDictionary.Add(Converter.Form, "Item 2")
MyDictionary.Add(Converter.Ascx, "Item 3")
...

现在我运行一个循环的 XML 文件并提取根节点的名称:

Dim document As New XmlDocument
document.Load(File.FullName)

Dim rootName As String = document.DocumentElement.Name

根名称与常量名称匹配。要从字典中获取项目的值,我可以使用如下内容:

Select Case rootName.ToUpper
    Case "Xsl".ToUpper
        DictionaryValue = MyDictionary(Class.Xsl)
    Case "Form".ToUpper
        DictionaryValue = MyDictionary(Class.Form)
    Case "Ascx".ToUpper
        DictionaryValue = MyDictionary(Class.Ascx)
    ...
    Case Else
End Select

如果添加或删除常量,我还必须更改选择。有没有另一种方法来获取常量的值?类似的东西

DictionaryValue = MyDictionary(SomeFunctionToGetConstantValue(rootName))

感谢您的回复。

【问题讨论】:

  • 请参阅stackoverflow.com/questions/1456518/… 以获取有关如何获取常量列表及其值的示例。然后查看stackoverflow.com/questions/1308507/… 以获得更简洁的示例来查找常量。另一方面,你真的需要它们是单独的常量吗?你能跳过常量只用字典吗?
  • 我可以在这两个链接的帮助下解决它。谢谢。我使用的常量是因为该过程被拆分为两个程序集。字典的常量定义和分析包含在 MustInherit 类中,在另一个程序集中,该类被继承,字典被值填充。为了避免多次写入值,我使用了这些常量。

标签: vb.net constants dynamic-programming generic-collections


【解决方案1】:

试试这个:

For Each sKey As String In MyDictionary.Keys
    If rootName.Equals(sKey, StringComparison.CurrentCultureIgnoreCase) Then
        DictionaryValue = MyDictionary(sKey)
        Exit For
    End If
Next

至少会减少select case中的编码量。

【讨论】:

  • 感谢您的回复。这是一个可行的解决方案,但@Abraham 的提示将我引向了一个更优雅的实现。
  • @mburm 为什么不添加您更优雅的解决方案作为公认的答案并照亮我们所有人?
【解决方案2】:

@Clara Onager

我使用的解决方案如下

Me.GetType.GetField(
    "Xsl",
    Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static Or System.Reflection.BindingFlags.FlattenHierarchy
).GetValue(Nothing)

【讨论】:

    【解决方案3】:

    这有点夸张,但我认为它总体上提供了一个非常优雅的解决方案。它是这样使用的:

    Public Class ConstantsExample
    
        Public Sub UseConstant()
    
            Dim value As String = Constants.Types(TypeA)
            Dim category As String = Constants.Categories(General)
    
        End Sub
    
    End Class
    

    如您所见,使用它的代码尽可能短。它确实依赖于一大堆源代码:

    Public Enum TypeCodes
        <Description("Type A")> TypeA = 0
        <Description("Type B")> TypeB
        <Description("Type C")> TypeC
    End Enum
    
    Public Enum CategoryCodes
        <Description("General")> General = 0
        <Description("Specific")> Specific
        <Description("Other")> Other
    End Enum
    
    Public NotInheritable Class Constants
    
    #Region "Resources"
    
        Private Shared myTypes As Dictionary(Of TypeCodes, ConstantItem) = Nothing
    
        Public Shared ReadOnly Property Types() As Dictionary(Of TypeCodes, ConstantItem)
            Get
                If myTypes Is Nothing Then
                    myTypes = New Dictionary(Of TypeCodes, ConstantItem)
                    BuildTypes(myTypes)
                End If
                Return myTypes
            End Get
        End Property
    
        Private Shared Sub BuildTypes(ByRef dict As Dictionary(Of TypeCodes, ConstantItem))
            With dict
                .Add(TypeCodes.TypeA, New ConstantItem(TypeCodes.TypeA.Description, "Type A are..."))
                .Add(TypeCodes.TypeB, New ConstantItem(TypeCodes.TypeB.Description, "Type B are..."))
                .Add(TypeCodes.TypeC, New ConstantItem(TypeCodes.TypeC.Description, "Type C are..."))
            End With
        End Sub
    
    #End Region
    
    #Region "Categories"
    
        Private Shared myCategories As Dictionary(Of CategoryCodes, ConstantItem) = Nothing
    
        Public Shared ReadOnly Property Categories() As Dictionary(Of CategoryCodes, ConstantItem)
            Get
                If myCategories Is Nothing Then
                    myCategories = New Dictionary(Of CategoryCodes, ConstantItem)
                    BuildCategories(myCategories)
                End If
                Return myCategories
            End Get
        End Property
    
        Private Shared Sub BuildCategories(ByRef dict As Dictionary(Of CategoryCodes, ConstantItem))
            With dict
                .Add(CategoryCodes.General, New ConstantItem(CategoryCodes.General.Description, "General category"))
                .Add(CategoryCodes.Specific, New ConstantItem(CategoryCodes.Specific.Description, "Specific category"))
                .Add(CategoryCodes.Other, New ConstantItem(CategoryCodes.Other.Description, "Other category"))
            End With
        End Sub
    
    #End Region
    
    End Class
    
    Public NotInheritable Class ConstantItem
    
    #Region "Constructors"
        ''' <summary>
        ''' Default constructor.
        ''' </summary>
        Public Sub New()
            'Do nothing
        End Sub
        ''' <summary>
        ''' Simple constructor.
        ''' </summary>
        Sub New(value As String)
            Me.Name = value
            Me.Description = value
        End Sub
        ''' <summary>
        ''' Proper constructor.
        ''' </summary>
        Sub New(name As String, description As String)
            Me.Name = name
            Me.Description = description
        End Sub
    
    #End Region
    
        Property Name As String
        Property Description As String
    
        ''' <summary>
        ''' See http://stackoverflow.com/questions/293215/default-properties-in-vb-net
        ''' </summary>
        Public Shared Widening Operator CType(value As String) As ConstantItem
            Return New ConstantItem(value)
        End Operator
        ''' <summary>
        ''' See http://stackoverflow.com/questions/293215/default-properties-in-vb-net
        ''' </summary>
        Public Shared Widening Operator CType(value As ConstantItem) As String
            Return value.Name
        End Operator
    
    End Class
    

    请注意使用Widening Operator 以省去必须键入.Item。如果您不想使用Widening Operator,那么只需简单的注释即可将Constants.Types(TypeA) 更改为Constants.Types.Item(TypeA)

    这是您可能需要的描述扩展:

    Public Module Extensions
        Private Enum SampleDescription
            <Description("Item One")> ItemOne = 1
            <Description("Item Two")> ItemTwo = 2
            <Description("Item Three has a long description")> ItemThree = 3
        End Enum
        ''' <summary>
        ''' This procedure gets the description attribute of an enum constant, if any. Otherwise it gets 
        ''' the string name of the enum member.
        ''' </summary>
        ''' <param name="value"></param>
        ''' <returns></returns>
        ''' <remarks>Usage:  myenum.Member.Description()
        ''' Add the Description attribute to each member of the enumeration.</remarks>
        <Extension()> _
        Public Function Description(ByVal value As [Enum]) As String
            Dim fi As Reflection.FieldInfo = value.GetType().GetField(value.ToString())
            Dim aattr() As DescriptionAttribute = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
            If aattr.Length > 0 Then
                Return aattr(0).Description
            Else
                Return value.ToString()
            End If
        End Function
    
    End Module
    

    这些是我使用的 Imports 语句(程序集称为 MyPatterns):

    Imports System.ComponentModel
    Imports MyPatterns.TypeCodes
    Imports MyPatterns.CategoryCodes
    

    导入这两个“代码”允许您不使用缩短代码的 Enum 前缀。

    【讨论】:

      猜你喜欢
      • 2011-07-28
      • 2020-03-13
      • 2011-09-03
      • 2011-10-06
      • 2013-09-16
      • 1970-01-01
      • 2020-09-02
      相关资源
      最近更新 更多