【问题标题】:VB.NET: Instantiate a nested property by reflectionVB.NET:通过反射实例化嵌套属性
【发布时间】:2018-08-20 15:38:24
【问题描述】:

我想通过反射设置属性的值。在这个thread 中,他们提出了一个解决方案。但是解决方案的问题在于它没有实例化属性。但是我想在必要时检查并实例化这些属性。我的 DTO 是:

Public Class root
    Public Property Printing() As rootPrinting
End Class

Public Class rootPrinting
    Public Property Printer() As String
    Public Property PrinterBatch() As String
End Class

现在为了设置属性,我定义了以下函数:

Public Sub SetProperty(ByVal target As Object, ByVal compoundProperty As String, ByVal value As Object)
    Dim properties As String() = compoundProperty.Split("."c)
    For i As Integer = 0 To properties.Length - 1 - 1
        Dim propertyToGet As PropertyInfo = target.[GetType]().GetProperty(properties(i))
        target = propertyToGet.GetValue(target, Nothing)
        if IsNothing(target) then
            if propertyToGet.PropertyType.IsClass then
                target = Activator.CreateInstance(propertyToGet.PropertyType)
            End If
        End If
    Next

    Dim propertyToSet As PropertyInfo = target.[GetType]().GetProperty(properties.Last())
    propertyToSet.SetValue(target, value, Nothing)
End Sub

那我这样称呼它:

Dim configObject as New root
SetProperty(configObject , "Printing.Printer","skjfkd")

如果在调用SetProperty(configObject,...) 之前我实例化了configObject.Printing 那么它会正常工作:

Dim configObject as New root
configObject.Printing = new rootPrinting()
SetProperty(configObject , "Printing.Printer","skjfkd") 

否则调用SetProperty(...)后,configObject.Printing将是Nothing
似乎在调用Activator.CreateInstance(propertyToGet.PropertyType) 时,对原始对象的引用丢失了。当函数中的对象真正初始化时,主对象仍然是Nothing。如何正确实例化类属性?

【问题讨论】:

  • DTO 类在您的示例中具有公共构造函数和属性。我假设在实际项目中这些都是私有的?
  • @ParrishHusband 不,在实际项目中,这些属性也是公开的。只有我有绑定到属性的私有成员。但是为了缩短文本,我已经为此示例更改了它。

标签: vb.net reflection propertyinfo


【解决方案1】:

这个问题/答案对我很有帮助(感谢 Code Pope!),我需要 C# 中的相同代码:

public void SetProperty(object target, string compoundProperty, object value)
{
    var properties = compoundProperty.Split('.');

    for (int i=0; i < (properties.Length - 1); i++)
    {
        var propertyToGet = target.GetType().GetProperty(properties[i]);
        var property_value = propertyToGet.GetValue(target, null);
        if (property_value == null)
        {
            if (propertyToGet.PropertyType.IsClass)
            {
                property_value = Activator.CreateInstance(propertyToGet.PropertyType);
                propertyToGet.SetValue(target, property_value);
            }
        }
        target = property_value;
    }

    var propertyToSet = target.GetType().GetProperty(properties.Last());
    propertyToSet.SetValue(target, value);
}

【讨论】:

    【解决方案2】:

    好的。问题解决了。为了解决这个问题,代码必须修改如下:

    Public Sub SetProperty(ByVal target As Object, ByVal compoundProperty As String, ByVal value As Object)
    
       Dim properties As String() = compoundProperty.Split("."c)
    
       For i As Integer = 0 To properties.Length - 1 - 1
          Dim propertyToGet As PropertyInfo = target.GetType().GetProperty(properties(i))
          Dim property_value = propertyToGet.GetValue(target, Nothing)
          If IsNothing(property_value) Then
             If propertyToGet.PropertyType.IsClass Then
                property_value = Activator.CreateInstance(propertyToGet.PropertyType)
                propertyToGet.SetValue(target, property_value)
             End If
          End If
          target = property_value
       Next
    
       Dim propertyToSet As PropertyInfo = target.GetType().GetProperty(properties.Last())
       propertyToSet.SetValue(target, value)
    
    End Sub
    

    【讨论】:

      猜你喜欢
      • 2021-03-23
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 2020-07-10
      • 1970-01-01
      • 1970-01-01
      • 2020-10-30
      • 1970-01-01
      相关资源
      最近更新 更多