3

的动态值,如果有有常量的定义如下:VB.NET:获取常量

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 

根名称与cons的名称匹配坦。从字典中获得一个项目的价值,我可以用这样的:

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)) 

感谢您的任何回应。

+1

请参阅http://stackoverflow.com/questions/1456518/how-to-obtain-a-list-of-constants-in-a-class-and-their-values?rq=1了解如何获取常量及其值的列表。然后,请参阅http://stackoverflow.com/questions/1308507/reflecting-constant-properties-fields-in-net/1308604#1308604,以获取查找常量的更简洁的示例。另一方面,你真的需要它们是单独的常量吗?你可以跳过常数,只用字典吗? – Abraham

+0

我可以在两个链接的帮助下解决它。谢谢。我使用的常量,因为该进程分为两个程序集。常量定义和字典分析包含在一个MustInherit类中,在另一个程序集中,这个类被继承并且字典被填充值。为了避免多次写入这些值,我使用了这些常量。 – mburm

回答

2

@Clara野驴

我的解决方案我所用的是以下

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

试试这个:

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

至少会降低在选择情况下的编码量。

+0

感谢您的回复。这是一个有效的解决方案,但@Abraham的提示让我更加优雅的实现。 – mburm

+1

@mburm为什么不把你更优雅的解决方案作为公认的答案来添加,并照亮我们所有人? –

2

这是一个有点弥天大谎,但我认为它总体提供了一个非常完美的解决方案。这是如何使用它:

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 

而且这些都是进口的语句我用(大会被称为MyPatterns):

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

导入两个“规范”允许你没有为缩短代码的Enum添加前缀。