【问题标题】:Can a class's properties be assigned using a lookup, or must each property be assigned individually?可以使用查找来分配类的属性,还是必须单独分配每个属性?
【发布时间】:2014-11-30 18:56:57
【问题描述】:

VS2013,Visual Basic

我有一个有很多属性的类。

Public Class
  Property 1
  .
  .
  Property N
End Class

我有一个名称值对列表

name1, value1
.
.
nameN, valueN

名称值对中的值将分配给属性值。

VB 是否有一种方法可以让我使用其中一个名称并使用它来“查找”类属性,选择它并为其分配值,循环遍历名称-值对以进行所有分配?

我没有看到我定义的类附加了一个方法。我应该以不同的方式定义我的班级吗?我使用 EF6 Code First 方法中的 Class 来创建后备数据库。

在我看来,另一种方法是逐个列出每个 Class 属性,查找名称并分配值,但这似乎是一种乏味的做事方式。

只是想我会问。也许有更好的方法来做到这一点。

谢谢。

最好的问候, 艾伦

【问题讨论】:

  • 您可以使用反射来做到这一点。有许多组件会自动将数据从一种类型映射到另一种类型,例如实体到 DTO,这样做就是为了确定要获取和设置的属性。
  • Dim obj As New Example With {.A = "asdf", .B = 42, .C = 3.14}
  • @Mark,是的,其他帖子也很有用。谢谢。

标签: vb.net


【解决方案1】:

共有三个课程可以帮助您; TypeDescriptorPropertyDescriptorPropertyDescriptorCollection。它们都位于System.ComponentModel 命名空间中。

Imports System.ComponentModel

我们将在此示例中使用以下类:

Public Class Foo
    'Implements ICustomTypeDescriptor (Optional)

    Public Property A() As String
    Public Property B() As Date
    Public Property C() As Integer
    Public Property D() As Boolean

    Public Overrides Function ToString() As String
        Return String.Format("A='{0}', B='{1}', C='{2}', D='{3}'", Me.A, Me.B, Me.C, Me.D)
    End Function

End Class

通过调用TypeDescriptor类的静态方法GetProperties获取所有属性。它返回PropertyDescriptor 类的集合——你的属性。然后您只需调用SetValue 和/或GetValue 方法。请注意,您可以通过实现ICustomTypeDescriptor 接口来实现自定义类型描述符。

Private Sub RunTest()

    Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(Foo))
    Dim ignoreCase As Boolean = True
    Dim foo1 As New Foo()

    properties.Find("A", ignoreCase).SetValue(foo1, "hello")
    properties.Find("B", ignoreCase).SetValue(foo1, Date.Now)
    properties.Find("C", ignoreCase).SetValue(foo1, 1234I)
    properties.Find("D", ignoreCase).SetValue(foo1, True)

    'Get property value:
    'Dim a As String = CType(properties.Find("A", ignoreCase).GetValue(foo1), String)

    Debug.WriteLine(foo1.ToString())

End Sub

输出:(immediate window)

A='你好',B='30.11.2014 11:14:39',C='1234',D='True'


扩展

为了进一步扩展这一点,可以创建一些扩展方法。

Imports System.Runtime.CompilerServices

Public Module Extensions

    <Extension()>
    Public Function GetProperty(Of TComponent)(component As TComponent, propertyName As String, Optional ByVal ignoreCase As Boolean = True) As Object
        Return TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).GetValue(component)
    End Function

    <Extension()>
    Public Function GetProperty(Of TComponent, TValue)(component As TComponent, propertyName As String, Optional ByVal ignoreCase As Boolean = True) As TValue
        Return CType(TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).GetValue(component), TValue)
    End Function

    <Extension()>
    Public Sub SetProperty(Of TComponent)(instance As TComponent, propertyName As String, value As Object, Optional ByVal ignoreCase As Boolean = True)
        TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).SetValue(instance, value)
    End Sub

End Module

现在通过名称设置/获取属性值非常容易。

Private Sub RunTest()

    Dim foo1 As New Foo()

    foo1.SetProperty("A", "hello")
    foo1.SetProperty("B", Date.Now)
    foo1.SetProperty("C", 1234I)
    foo1.SetProperty("D", True)

    'Get property value:
    'Dim a As String = CType(foo1.GetProperty("A"), String)
    'Dim a As String = foo1.GetProperty(Of String)("B")

    Debug.WriteLine(foo1.ToString())

End Sub

输出:

A='你好',B='30.11.2014 11:18:17',C='1234',D='真'

【讨论】:

  • 太好了,谢谢。能够复制您答案的第 1 部分,它真正回答了我原来的问题。我无法复制第 2 部分只是因为我还不熟悉扩展概念,但我可以在您的代码中了解它是如何工作的。
  • 太棒了!扩展方法的概念并不难。只需将一个新的类文件添加到您的项目中,并用我的扩展模块代码替换自动生成的代码,重建。您可以阅读更多关于扩展方法的信息 here
猜你喜欢
  • 2014-09-13
  • 2018-06-28
  • 2013-04-03
  • 2018-03-22
  • 2012-08-25
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多