VB.NET:通过反射实例化一个嵌套的属性

VB.NET: Instantiate a nested property by reflection

我想通过反射设置属性的值。在这个 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。如何正确实例化 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))
      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

这个 question/answer 对我很有帮助(感谢 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);
}