在不调用构造函数的情况下递归实例化子类?

时间:2017-04-13 19:31:44

标签: vb.net class recursion constructor system.reflection

假设以下示例类模仿从XSD文件生成的类的类型:

Public Class MyClass
    Public Class MyInnerClass1
        Public Class MyInnerInnerClass1
            Public Property MyProp1 as string
            Public Property MyProp2 as string
            ...
        End Class
        ...
        Public Property MyInnerInnerClassProp1 as MyInnerInnerClass1
    End Class

    Public property MyInnerClassProp1 as MyInnerClass1
    Public property MyInnerClassProp2 as MyInnerClass2
    ...
End Class

请注意,没有构造函数。在特定情况下,内部类的级别在达到Property MyProp1 as string之类的基本属性之前可以达到5级深度,可能是循环的。

如何递归遍历所有公共可写属性并将它们初始化为没有构造函数的该对象类型的新实例?

例如,这是我目前的代码,目前仅深入一级?

 Private Shared Sub InitProperties(obj As Object)
    For Each prop As Object In obj.[GetType]().GetProperties(BindingFlags.[Public] Or BindingFlags.Instance).Where(Function(p) p.CanWrite)
        Dim type__1 = prop.PropertyType
        Dim constr = type__1.GetConstructor(Type.EmptyTypes)
        'find paramless const
        If type__1.IsClass Then
            Dim propertyInstance = DirectCast(FormatterServices.GetUninitializedObject(type__1.GetType()), Object)

            'Dim propInst = Activator.CreateInstance(type__1)
            'prop.SetValue(obj, propInst, Nothing)
            InitProperties(propertyInstance)
        End If
    Next
End Sub

1 个答案:

答案 0 :(得分:0)

我对您的代码进行了一些小编辑,以使其适用于您提供的示例类。 (虽然我确实将字符串属性更改为Integer以避免出现一个错误。)我还添加了一个用于限制递归调用次数的参数,并在初始化之前检查属性是否为空。 (如果在静态类之间有循环引用,则此检查只会有所不同。)

Private Shared Sub InitProperties(obj As Object, Optional ByVal depth As Integer = 5)
    For Each prop As PropertyInfo In obj.GetType().GetProperties(BindingFlags.Public Or BindingFlags.Instance).Where(Function(p) p.CanWrite)
        Dim type__1 As Type = prop.PropertyType

        If type__1.IsClass And IsNothing(prop.GetValue(obj, Nothing)) And depth > 0 Then
            Dim propertyInstance As Object = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type__1)
            prop.SetValue(obj, propertyInstance, Nothing)
            InitProperties(propertyInstance, depth - 1)
        End If
    Next
End Sub