Использование инициализаторов объектов VB.NET в фабричном шаблоне

Я написал базовый класс, из которого я хочу получить несколько дочерних классов (в данном случае классы Windows Form), и я использую шаблон Factory, чтобы поддерживать коллекцию дочерних экземпляров, так что форма может иметь только один экземпляр для каждого значения первичного ключа (своего рода смесь шаблонов Factory и Singleton).

Я использую следующий код в классе базовой формы:

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

Идея состоит в том, чтобы создать дочернюю форму (например, UserInfoForm), которая наследуется от базовой формы, и создать ее экземпляр для пользователя № 42 следующим образом:

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

Все это работает как задумано.

Однако у UserInfoForm теперь есть некоторые свойства, которые я хочу установить, и я хотел бы установить их с помощью инициализаторов объектов, а не после того, как форма будет создана фабрикой, например так:

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

Есть ли способ объединить эти два метода, чтобы у меня была фабрика и инициализатор?

Я не ищу:

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

...потому что базовый класс также имеет метод ShowForm(), который принимает дополнительные параметры базовой формы, оборачивает функцию GetForm() и показывает форму.


person MCattle    schedule 30.03.2012    source источник
comment
Я не понимаю. Почему ваш метод ShowForm() означает, что вы не можете установить свойства обычным способом?   -  person svick    schedule 31.03.2012
comment
ShowForm() был общим методом, который вызывал GetForm() внутри, устанавливал некоторые параметры макета (MDI Parent и еще много чего), а затем вызывал Me.Show(). Она вызывалась вместо GetForm(), но оказалось, что мы почти всегда хотим вызывать ShowForm().   -  person MCattle    schedule 31.03.2012
comment
Мы переработали его, чтобы упростить ShowForm(), который я опубликую в качестве ответа ниже. Однако мне все еще любопытно, как объединить инициализаторы объектов с фабричным конструктором.   -  person MCattle    schedule 31.03.2012
comment
(Мы опубликуем наше решение через 6 часов, когда StackOverflow позволит новичку, такому как я, ответить на мой собственный вопрос. :-)   -  person MCattle    schedule 31.03.2012
comment
К сведению, я добавил в Microsoft предложение разрешить anyClassExpression With {.Property=Value,...} здесь   -  person Mark Hurd    schedule 01.04.2012


Ответы (2)


Чтобы получить настоящие инициализаторы объектов, по определению вы должны использовать New... With.

И поскольку вы хотите иногда НЕ создавать новый объект, это не вариант.

В зависимости от ваших других требований, ваше решение может состоять в том, чтобы каждый раз использовать новый новый объект, но инкапсулировать синглтон внутри или использовать что-то похожее на:

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

который может быть упрощен до Dim formCurrentUser = PKSingletonForm.GetForm(of UserInfoForm)(42) : With formCurrentUser, если дополнительная функциональность, доступная в приведенной выше конструкции (т.е. что GetForm может возвращать другой тип, который может иметь больше или меньше доступных свойств и методов) не требуется.

person Mark Hurd    schedule 01.04.2012

Наш метод ShowForm() был написан следующим образом:

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

Наше решение состояло в том, чтобы убрать Shared (и Generics), чтобы упростить ShowForm() до:

Public Sub ShowForm(<Several Parameters Here>)

   <Do Stuff with Parameters Here>

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

Таким образом, мы можем написать:

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

...так же как:

Dim formCurrentUser = PKSingletonForm.GetForm(of UserInfoForm)(42).ShowForm()
person MCattle    schedule 01.04.2012