views:

36

answers:

1

Hi all,

I have classes setup similar to this:

<DataContract()> _
Public MustInherit Class SystemTaskProcessBase

    Public MustOverride ReadOnly Property Name() As String
    Public MustOverride ReadOnly Property Description() As String

    Public MustOverride Property Result() As SystemTaskResult

    <DataMember()> _
    Private _TaskID As Integer = 0
    Public Property TaskID() As Integer
        Get
            Return _TaskID
        End Get
        Set(ByVal value As Integer)
            _TaskID = value
        End Set
    End Property

End Class

<DataContract()> _
Public Class RebootSystemTaskProcess
    Inherits SystemTaskProcessBase

    Private _Name As String = "Reboot System"
    Public Overrides ReadOnly Property Name() As String
        Get
            Return _Name
        End Get
    End Property

    Private _Description As String = "Task for the client to reboot itself internally."
    Public Overrides ReadOnly Property Description() As String
        Get
            Return _Description
        End Get
    End Property

    <DataMember()> _
    Public _Result As SystemTaskResult = SystemTaskResult.NotProcessed
    Public Overrides Property Result() As SystemTaskResult
        Get
            Return _Result
        End Get
        Set(ByVal value As SystemTaskResult)
            _Result = value
        End Set
    End Property

End Class

<DataContract()> _
Public Class DeleteFileSystemTaskProcess
    Inherits SystemTaskProcessBase

    Private _Name As String = "Delete File"
    Public Overrides ReadOnly Property Name() As String
        Get
            Return _Name
        End Get
    End Property

    Private _Description As String = "Task for the client to delete a local file."
    Public Overrides ReadOnly Property Description() As String
        Get
            Return _Description
        End Get
    End Property

    <DataMember()> _
    Public _Result As SystemTaskResult = SystemTaskResult.NotProcessed
    Public Overrides Property Result() As SystemTaskResult
        Get
            Return _Result
        End Get
        Set(ByVal value As SystemTaskResult)
            _Result = value
        End Set
    End Property

    <DataMember()> _
    Private _File As FileInfo
    Public Property File() As FileInfo
        Get
            Return _File
        End Get
        Set(ByVal value As FileInfo)
            _File = value
        End Set
    End Property

End Class

I need to use these classes on the client system, but also need to be able to create these "tasks" through a management interface. Each class (Task) that inherits the base, could have its own properties that are unique to each class, but at the same time, share the same common base class properties. For example, the above shows a reboot task and a delete file task, the delete file task needs to know which file to delete, so has a property for that. But the reboot task does not need this property. So when the management application is creating these tasks, it shouldn't provide a text box for the file property for the reboot task. There may be more tasks created at a later date with completely different properties.

How would I go about providing the WinForms management application a way to enumerate each class into a ListView for example, and allowing the user to create these tasks and filling in the dynamic properties that each class would have?

Desired functionality would be to create a task form that creates dynamic controls available for the properties as needed, depending on the public properties in each class, but at the same time have the base class properties available as well.

Any ideas are appreciated.

Thanks, Scott

A: 

If you need a highly customizable and extendable solution, then one way to go about doing it would be date driven approach. In one of my previous job, we had to create a dynamic UI based on client preference where field 1 was applicable to one client, but the same was not needed by another. Extending that approach to your question, you will need to have DB tables

TasksTable with following columns
1.TaskId
2.TaskName
3.ClassName  (you will use reflection to create an instance of it)

Another table with the actual fields for the tasks. Lets call it TaskFields for now.

TaskFields Table 
1. TaskFieldId
2. Property   (You can create another field to store the Name if you need to)
3. Enabled (bit)
4. SpecialFormat   <if you need to apply this and customize it based on some preference)

These are fairly small tables. Load them up when the app starts. In your app, bind your ListBox to the TaskName field in TasksTable. When a specific item is selected, dynamically create controls based on the values in TaskFields table for the selected Item. Create the class based on the ClassName field and associate create bindings to the controls generated.

This is complex, but the advantage you get is you can switch Off/On controls to show up.

EDIT: If you plan to use the attributes approach, following might be handy. Based on your examples, you are already marking the properties you need as Datamember. So you don't have to define any custom attribute, unless you have other properties which will not be used for user input but have themselves marked DataMember for other purposes.

Dim type As Type = GetType(yourClass)
Dim properties As PropertyInfo() = type.GetProperties()
Dim neededProperties = (From [property] In propertiesLet attributes = DirectCast([property].GetCustomAttributes(GetType(DataMemberAttribute), False), Attribute()) Where attributes.Count() > 0[property]).ToList()
SKG
@SKG Thanks for your reply. I'm really trying to keep this outside of a database right now. After posting my question I started reading up on custom attributes for classes and fields and then being able to read those flag values to determine if that field should have a control created for it or not. I think it's essentially doing the same thing you're suggesting, just eliminating the database need.
ScottN
@ScottN. See Edit for using reflection to get the properties needed.
SKG