Question

I have written a base class from which I wish to derive several child classes (in this case Windows Form classes), and I'm using a Factory pattern in order to maintain a collection of the child instances, so that a form can only have one instance per primary key value (sort of a mash-up of Factory and Singleton patterns.)

I'm using the following code in the base form class:

Public Class PKSingletonForm
   Inherits Form

   Protected _PKValue As Int32 = 0
   Protected _strFormKey As String = ""
   Protected Shared _dictForms As New Dictionary(Of String, PKSingletonForm)

   Public Shared Function GetForm(Of T As {PKSingletonForm, New})(Optional ByVal PKValue As Int32 = 0) As T
      '** Create the key string based on form type and PK.
      Dim strFormKey As String = GetType(T).Name & "::" & PKValue.ToString

      '** If a valid instance of the form with that key doesn't exist in the collection, then create it.
      If (Not _dictForms.ContainsKey(strFormKey)) OrElse (_dictForms(strFormKey) Is Nothing) OrElse (_dictForms(strFormKey).IsDisposed) Then
         _dictForms(strFormKey) = New T()
         _dictForms(strFormKey)._PKValue = PKValue
         _dictForms(strFormKey)._strFormKey = strFormKey
      End If

      Return DirectCast(_dictForms(strFormKey), T)
   End Function
End Class

The idea is to create a child form (called UserInfoForm, for example) that inherits from the base form, and create an instance of it for user #42 as follows:

Dim formCurrentUser = PKSingletonForm.GetForm(of UserInfoForm)(42)

All this works as intended.

However, the UserInfoForm now has some properties I wish to set, and I would like to set them using Object Initializers, as opposed to after the form is created by the factory, like so:

Dim formCurrentUser As New UserInfoForm With { .ShowDeleteButton = False, .ShowRoleTabs = False }

Is there any way to combine these two methods, so I've got the factory as well as the initializer?

I'm not looking for:

Dim formCurrentUser = PKSingletonForm.GetForm(of UserInfoForm)(42)
formCurrentUser.ShowDeleteButton = False
formCurrentUser.ShowRoleTabs = False

...because the base class also has a ShowForm() method that takes additional base form parameters, wraps the GetForm() function, and shows the form.

Was it helpful?

Solution 2

Our ShowForm() method was written as follows:

Public Shared Sub ShowForm(Of T As {BaseForm, New})(Optional ByVal PKValue As Int32 = 0, <Several Parameters Here>)

   Dim formShown As BaseForm = GetForm(Of T)(PKValue, isRepeatable)

   <Do Stuff with Parameters Here>

   formShown.Show()
   formShown.BringToFront()
End Sub

Our solution was to take out the Shared (and the Generics), to simplify ShowForm() to:

Public Sub ShowForm(<Several Parameters Here>)

   <Do Stuff with Parameters Here>

   Me.Show()
   Me.BringToFront()
End Sub

That way, we can write:

Dim formCurrentUser = PKSingletonForm.GetForm(of UserInfoForm)(42)
formCurrentUser.ShowDeleteButton = False
formCurrentUser.ShowRoleTabs = False
formCurrentUser.ShowForm(blah, blah)

...as well as:

Dim formCurrentUser = PKSingletonForm.GetForm(of UserInfoForm)(42).ShowForm()

OTHER TIPS

To get true Object Initializers, by definition you must use New ... With.

And because you want to sometimes NOT create a new object, that is not an option.

Depending upon your other requirements, your solution could be to change to use a fresh new object every time, but encapsulate the singleton inside, or to use something similar to:

Dim formCurrentUser As UserInfoForm 
With PKSingletonForm.GetForm(of UserInfoForm)(42)
  .ShowDeleteButton = False
  .ShowRoleTabs = False
  formCurrentUser = .Self
End With

which can be simplified to Dim formCurrentUser = PKSingletonForm.GetForm(of UserInfoForm)(42) : With formCurrentUser if the extra functionality available in the above construct (i.e. that GetForm can return another type that may have more or fewer properties and methods available) is not needed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top