lundi 7 août 2017

Change child class readonly property from parent class

I'm building an application in VB.NET that will use class inheritance extensively, and will be putting as much code as possible into the base class, including database actions. The issue i'm having is how to set a property of a derived class from the parent class. I can retreive the values, and set values of non readonly properties without issue, however there will be several cases where I want to set read-only properties through code, but still not let the user change these (Modified date / Created date for example). I've put together a quick console application that shows the issue;

Parent Class:

Public Class clsParent
    Private _ParentInteger As Integer = 0
    Public Property ParentInteger As Integer
        Get
            Return _ParentInteger
        End Get
        Set(value As Integer)
            _ParentInteger = value
        End Set
    End Property

    Public Sub PrintProperties()
        Dim t As Type = Me.GetType
        Console.WriteLine("Object type: '{0}'", t.ToString)
        Dim propInfos As PropertyInfo() = t.GetProperties()
        Console.WriteLine("The number of properties: {0}", propInfos.Length)
        Console.WriteLine("------------------------------------------------------------")
        For Each propInfo In propInfos
            Dim readable As Boolean = propInfo.CanRead
            Dim writable As Boolean = propInfo.CanWrite

            Console.WriteLine("   Property name: {0}", propInfo.Name)
            Console.WriteLine("   Property type: {0}", propInfo.PropertyType)
            Console.WriteLine("   Read-Write:    {0}", readable And writable)
            Console.WriteLine("   Value:         {0}", propInfo.GetValue(Me))
            Console.WriteLine("------------------------------------------------------------")
        Next

    End Sub

    Public Sub TryWriteProperties()
        Dim t As Type = Me.GetType
        Dim propInfos As PropertyInfo() = t.GetProperties()

        For Each propInfo In propInfos
            Console.WriteLine("------------------------------------------------------------")
            Console.WriteLine("   {0}", propInfo.Name)
            Try
                Console.WriteLine("      Old Value:     {0}", propInfo.GetValue(Me))
                propInfo.SetValue(Me, CInt(propInfo.GetValue(Me)) + 100)
                Console.WriteLine("      New Value:     {0}", propInfo.GetValue(Me))
            Catch ex As Exception
                Console.WriteLine("      Failed to set new value: {0}", ex.Message)
            End Try
        Next
    End Sub
End Class

And the child class;

Public Class clsChild
    Inherits clsParent

    Dim _ChildWritableInteger As Integer = 5
    Public Property ChildWritableInteger As Integer
        Get
            Return _ChildWritableInteger
        End Get
        Set(value As Integer)
            _ChildWritableInteger = value
        End Set
    End Property

    Dim _ChildReadOnlyInteger As Integer = 10
    Public ReadOnly Property ChildReadOnlyInteger As Integer
        Get
            Return _ChildReadOnlyInteger
        End Get
    End Property
End Class

And a simple sub to show the output;

Sub Main()
    Dim x As New clsChild
    x.PrintProperties()
    Console.WriteLine("Waiting...")
    Console.ReadLine()
    Do Until Console.ReadLine = "x"
        x.TryWriteProperties()
        Console.WriteLine("Waiting...")
    Loop
End Sub

This (quite rightly) shows me the error "Failed to set new value: Property set method not found." when it tries to set the "ChildReadOnlyInteger" property.

Object type: 'ConsoleApplication1.clsChild'
The number of properties: 3
------------------------------------------------------------
   Property name: ChildWritableInteger
   Property type: System.Int32
   Read-Write:    True
   Value:         5
------------------------------------------------------------
   Property name: ChildReadOnlyInteger
   Property type: System.Int32
   Read-Write:    False
   Value:         10
------------------------------------------------------------
   Property name: ParentInteger
   Property type: System.Int32
   Read-Write:    True
   Value:         0
------------------------------------------------------------
Waiting...


------------------------------------------------------------
   ChildWritableInteger
      Old Value:     5
      New Value:     105
------------------------------------------------------------
   ChildReadOnlyInteger
      Old Value:     10
      Failed to set new value: Property set method not found.
------------------------------------------------------------
   ParentInteger
      Old Value:     0
      New Value:     100
Waiting...

My question is, what is the best approach to use where the base class can modify either the property or the variable of a child class without exposing the property publicly as read/write and without having two properties linked to the same holding variable?





Aucun commentaire:

Enregistrer un commentaire