有没有办法在类中动态指定属性名称?

时间:2014-05-29 20:41:20

标签: vb.net object dynamic anonymous-types

VB.NET 2010~Framework 3.5

有没有办法动态指定类的属性名称?

有时我需要一个从Prop1和Prop2创建的列表 其他时候我需要一个从Prop2和Prop4等创建的列表。目标属性不是提前知道的,它们会随着应用程序的运行而不断变化。 。

Option Strict On
Option Explicit On
Public Class Form1

Private Class Things
    Public Property Prop1 As String
    Public Property Prop2 As String
    Public Property Prop3 As String
    Public Property Prop4 As String
End Class

Private Class SubThing
    Public Property P1 As String
    Public Property P2 As String
End Class

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim mainLst As New List(Of Things)

    Dim count As Integer

    Do Until count = 20
        mainLst.Add(New Things With {.Prop1 = count.ToString, _
                                     .Prop2 = (count + 1).ToString, _
                                     .Prop3 = (count + 2).ToString, _
                                     .Prop4 = (count + 3).ToString})
        count += 1
    Loop

    ' Need to dynamically pick properties From mainLst into subLst.
    ' The commented code below wont compile but demonstrates what I'm trying to do
    ' can this be done without looping?

    'Dim propNameA As String = "Prop1"  ' Dynamically specify a property name
    'Dim propNameB As String = "Prop4"
    'Dim subLst = From mainItem In mainLst
    '             Select New SubThing() With {.P1 = mainItem.propNameA, .P2 = mainItem.propNameB}


    ' This code below compiles but lacks the dynamics I need?
    Dim subLst = From mainItem In mainLst
                  Select New SubThing() With {.P1 = mainItem.Prop1, .P2 = mainItem.Prop4}
End Sub

3 个答案:

答案 0 :(得分:1)

最直接的方法是使用CallByNameMSDN Link)。我假设您的示例是您正在使用的简化版本,但似乎更好的方法是摆脱您的Prop1Prop2,{{1} }字符串属性,只需使用一个...,然后您可以将其编入索引,而无需将属性名称与索引值一起使用frankenstein。例如:

List(Of String)

不确定您的确切用例来自您的示例,但希望这可以指出您正确的方向。

答案 1 :(得分:1)

以下是使用反射作为helrich @建议的示例。 (您必须在.vb文件的顶部Imports System.Reflection

1)天真的控制台输出示例:

Dim thingType As Type = GetType(Things)
Dim prop1Property As PropertyInfo = thingType.GetProperty("Prop1")

Dim thingInstance As Things = New Things()
thingInstance.Prop1 = "My Dynamically Accessed Value"

Dim prop1Value = prop1Property.GetValue(thingInstance).ToString()
Console.WriteLine(prop1Value)

2)适应你的例子(“可能”有效,尚未测试):

Dim propNameA As String = "Prop1"  ' Dynamically specify a property name
Dim propNameB As String = "Prop4"

Dim propAPropInfo As PropertyInfo = GetType(Things).GetProperty(propNameA)
Dim propBPropInfo As PropertyInfo = GetType(Things).GetProperty(propNameB)

Dim subLst = From mainItem In mainLst
             Select New SubThing() With {.P1 = propAPropInfo.GetValue(mainItem).ToString(), .P2 = propBPropInfo.GetValue(mainItem).ToString()}

答案 2 :(得分:0)

Option Strict On
Option Explicit On
Imports System.Reflection
Module Module1

    Private Class SourceClass
        Public Property Prop1 As String
        Public Property Prop2 As String
        Public Property Prop3 As String
        Public Property Prop4 As String
    End Class

    Private Class SubClass
        Public Property P1 As String
        Public Property P2 As String
    End Class

    Sub Main()
        Dim mainLst As New List(Of SourceClass)

        Dim count As Integer

        Do Until count = 20  ' create source list 
            mainLst.Add(New SourceClass With {.Prop1 = count.ToString, _
                                              .Prop2 = (count + 1).ToString, _
                                              .Prop3 = (count + 2).ToString, _
                                              .Prop4 = (count + 3).ToString})
            count += 1
        Loop

        Dim propAInfo As PropertyInfo = GetType(SourceClass).GetProperty("Prop1")  ' Dynamically specify a property name
        Dim propBInfo As PropertyInfo = GetType(SourceClass).GetProperty("Prop3")

        ' create a list of SubClass from SourceClass
        Dim subLst = From mainItem In mainLst Select New SubClass() _
                                              With {.P1 = propAInfo.GetValue(mainItem, Nothing).ToString, _
                                                    .P2 = propBInfo.GetValue(mainItem, Nothing).ToString}

        count = 0
        Do Until count = subLst.Count
            Debug.WriteLine(subLst(count).P1 & "~" & subLst(count).P2)
            count += 1
        Loop

    End Sub

End Module