属性List(Of Int32)上的PropertyInfo.SetValue

时间:2015-04-08 00:42:08

标签: .net vb.net system.reflection

我有一个包含一些列表属性的类:

Public Class ListPropertiesClass
    Public Property Id As List(Of Int32)
End Class

另一个我使用Reflection的课程:

Public Class Test

   Public Sub MySub()

      Dim IdentityValue as Int32 = 100
      Dim PropertyName as String = "Id"
      Dim LPC as new ListPropertiesClass
      Dim pInfo As PropertyInfo

      pInfo = LPC.GetType().GetProperty(PropertyName)
      If Not pInfo Is Nothing Then

          pInfo.SetValue(LPC, Convert.ToInt32(IdentityValue), Nothing)

       End If

   End Sub

End Class

但是当我尝试使用它时它不起作用,因为我试图将类型Int32的值设置为List 1,我如何使用PropertyInfo.SetValue添加列表Itens?添加后,如何使用反射获取值以获取列表特定索引的值

pInfo.GetValue(LPC, Nothing)

如果有人能帮助我,我会很高兴。感谢。

2 个答案:

答案 0 :(得分:0)

你必须先得到当前属性的值(并检查它),如下所示

这是例如,因为我不记得vb.net的确切语法

Dim pValue = pInfo.GetValue(LPC, Nothing)
Dim castedValue As List(Of Integer) = TryCast(pValue, List(Of Integer))

If castedValue Is Nothing Then
   castedValue = New List(Of Integer)()
End If
castedValue.Add(IdentityValue)
pInfo.SetValue(LPC, Convert.ToInt32(IdentityValue), Nothing)

答案 1 :(得分:0)

  • 首先,正如您已经指出的那样,您无法为Int32属性分配List(Of Int32)值。

  • 其次,我不确定你要完全尝试完成什么,但我会同意它 - 让我们分配一个的新实例使用

  • 创建了 List(Of Int32)实例对该媒体资源的引用

这里什么都没有:

Dim newList As New List(Of Int32)
pInfo.SetValue(LPC, newList, Nothing)

现在,您可以在列表中添加内容(您已经有了对它的引用):

Dim newList As New List(Of Int32)
pInfo.SetValue(LPC, newList, Nothing)

newList.Add(10)
newList.Add(11);

它不是存储列表的属性。 该属性存储引用(4字节= 32位长的数值)。 引用,指针或地址不是实际的实例。

您可以使用引用对实例执行操作,并且可以对同一实例进行多次引用。

观点变更

假设你对我刚刚做的反射玩兴趣不感兴趣。假设您同意以下修改:

Public Class ListPropertiesClass
    Public Property Id As List(Of Int32)

    Sub New()
        Property = New List(Of Int32)
    End Sub
End Class

基本上,List(Of Int32)的每个实例都需要一个ListPropertiesClass的实例,这是一个微不足道的事情,所以让我们简单地创建List(Of Int32)及其中的Int32 #39; s包装 - 这里没有反思。

现在,假设您要使用Reflection将LPC.Property.Add(10) ' LINE 1 值添加到该列表中。

首先看看如何在没有反思的情况下实现这一目标:

Dim theList As List(Of Int32)     ' LINE 2
theList = LPC.Property            ' LINE 3
theList.Add(10)                   ' LINE 4

可以翻译成这个等效的代码:

' LINE 1

如果您不完全确定最后3行与' LINE 2注释的行具有完全相同的效果,那么我建议您刷新一般OOP中的类,实例和引用。< / p>

现在,让我们看看最后3行实际上在做什么(不使用Reflection - ):

  • ' LINE 3只是一个变量声明
  • ' LINE 4获取操作,后跟作业
  • ' LINE 3是方法的调用

因此,这里的关键方面是List(Of Int32)获取而不是设置

现在你要做的是:

我们不会声明一个可以存储Object引用的变量,而是声明一个可以存储' so this line ' Dim theList as List(Of Int32) ' becomes this line Dim theList As Object 引用的变量

' so this line
' theList = LPC.Property
' becomes this line
theList = LPC.GetType().GetProperty(PropertyName).GetValue(LPC, Nothing)

而不是&#34;定期进入&#34;并将属性的值赋给变量我们仍然进行赋值,但我们使用反射

获取值
GetValue

(请注意跟踪List(Of Int32)电话)

我们不是简单地使用指向List(Of Int32)实例的Add引用向列表添加值,而是使用Object引用来调用List(Of Int32)方法。指出 - 你猜对了 - ' so this line ' theList.Add(10) ' becomes this line theList.GetType().GetMethod("Add").Invoke(theList, New Object() { 10 }) 实例

Dim theList As Object
theList = LPC.GetType().GetProperty(PropertyName).GetValue(LPC, Nothing)
theList.GetType().GetMethod("Add").Invoke(theList, New Object() { 10 })

注意Invoke方法。单击有关它的msdn文章的链接。

总结一下,看起来应该是这样的:

Object

现在,您可以轻松地将List(Of Int32)引用转换为Add引用并调用List(Of Int32)方法而不用反射。在这种情况下,局部变量可以是Dim theList As List(Of Int32) theList = TryCast(LPC.GetType().GetProperty(PropertyName).GetValue(LPC, Nothing), List(Of Integer)) theList.Add(10)

{{1}}
祝你好运!