2016-01-17 3 views
0

Я связываю создание универсального решения для создания экземпляров моих форм. с использованием поведения однопользовательского режима в vb.net. Но это не работает в любом случае и всегда защищает меня компилировать:Создание общего определения для Singleton объектов/форм

Public Class SingletonGenerator(Of TForm) 

    Private _inst As Object 

    Public ReadOnly Property Instance As SingletonInstance(Of TForm) 
     Get 
      If _inst Is Nothing Then 
       _inst = New TForm() 
      End If 
      Return _inst 
     End Get 
    End Property 

End Class 

Но эта ошибка ограничивает меня продолжать:

Ошибка 9 «New» не может быть использован параметр типа, не имеет «нового» ограничения.

И я не уверен, если я заменю свой код с New Form() он работает, как ожидалось (потому что создавать объекты родительского класса form() и может потерять некоторые инициализации в дочернем классе.)

Может кто-нибудь, пожалуйста, объясните почему это происходит или как я могу иметь одиночные экземпляры объектов в пути OOP, которые не требуют копирования/вставки этих общих строк кода, которые используются в singleton для каждого нового определенного класса?

+0

Если у вас нет аргументов для перехода в t он конструктор, просто добавьте ограничение New. Я считаю, что синтаксис в VB.NET есть '(Of TForm As New)'. – Lucero

+0

Где именно шаблон singleton применяется в этом коде? Я смущен. В этом примере у вас должен быть экземпляр «SingletonGenerator» для каждой формы, с которой вы хотите работать. – shadow

+0

@ Lucero Вы комментируете правильный ответ, и это было то, что я не знал, «что я могу разместить новое ключевое слово как тип». Благодарю. –

ответ

2

Вам необходимо убедить компилятор, что тип TForm фактически имеет конструктор без параметров, так что New TForm() никогда не сможет провалиться. Для этого требуется a constraint.

Не единственное, что вам нужно сделать, объект формы становится непригодным, когда он закрыт. И вам придется создать еще один, чтобы повторно отобразить его. Невыполнение этого требования вызывает ObjectDisposedException во время выполнения. Другими словами, вас должно заинтересовать Disposed event. Для этого требуется дополнительное ограничение, параметр типа TForm всегда должен выводиться из формы. Требуется, чтобы убедить компилятор, что это нормально использовать событие. Подтверждение:

Public Class SingletonGenerator(Of TForm As {Form, New}) 

    Private _inst As TForm 

    Public ReadOnly Property Instance As TForm 
     Get 
      If _inst Is Nothing Then 
       _inst = New TForm() 
       AddHandler _inst.Disposed, Sub() _inst = Nothing 
      End If 
      Return _inst 
     End Get 
    End Property 

End Class 

Будьте немного осторожны с этим, вы рисуете себя в углу. Вы можете использовать этот код только для создания объектов формы, конструктор которых не принимает аргументов. На практике вы можете обнаружить, что они часто нуждаются в этом.

+0

Ты отличный человек, я никогда не знал, что я могу определить общие классы по этому шаблону: 'Of TForm As {Form, New}'. –

+0

О конструкторах. Я уверен, что не буду использовать параметры для форм и формы для размещения. Я обработаю это, скрывая, а не закрывая. Это было именно то, что я искал, и я не знал, спасибо. –

1

Проверьте этот код:

Module Startup 

    Public Sub Main() 
     Dim f As Form = FormsManager.Instance.GetForm(Of Form1)() 

     f.ShowDialog() 

     Dim f1 As Form = FormsManager.Instance.GetForm(Of Form1)() 

     f1.ShowDialog() 
    End Sub 

End Module 

Public Class FormsManager 
    Private Shared _formsManager As FormsManager 
    Private _forms As List(Of Form) 

    Public Shared ReadOnly Property Instance As FormsManager 
     Get 
      If (_formsManager Is Nothing) Then 
       _formsManager = New FormsManager 
      End If 

      Return _formsManager 
     End Get 
    End Property 


    Private Sub New() 
     If _forms Is Nothing Then _forms = New List(Of Form) 
    End Sub 

    Public Function GetForm(Of T As {Form, New})() As Form 
     Dim f As Form = _forms.Where(Function(o) o.GetType = GetType(T)).SingleOrDefault 

     If f Is Nothing Then 
      f = New T 
      _forms.Add(f) 
     End If 

     Return f 
    End Function 

End Class 
+0

Спасибо, что поделились своим кодом, но это было не то, что я имел в виду, и ответ Ханса Пассенса помог мне завершить мою идею, и я поделюсь ею сейчас; Я считаю, что это проще и гибче, чем делать это таким образом. +1 для вашей помощи. –

0

Это то, что я, наконец, произвел (общий Синглтон формы генератора):

Imports System.Windows.Forms 
Imports System.Runtime.CompilerServices 

<HideModuleName()> _ 
Public Module SingletoneForms 

    <Extension> _ 
    Public Function GetInstance(Of TForm As {Form, New})(ByRef obj As TForm) As TForm 
     Return SingletonForm(Of TForm).Instance 
    End Function 

    Public Class SingletonForm(Of TForm As {Form, New}) 

     Private Shared WithEvents _inst As TForm 

     Public Shared Property Instance As TForm 
      Get 
       If _inst Is Nothing Then 
        SetInstance(New TForm()) 
       End If 
       Return _inst 
      End Get 
      Set(value As TForm) 
       SetInstance(value) 
      End Set 
     End Property 

     Private Shared Sub SetInstance(ByVal newInst As TForm) 
      If _inst IsNot Nothing Then 
       RemoveHandler _inst.FormClosing, AddressOf FormClosing 
      End If 
      _inst = newInst 
      AddHandler _inst.FormClosing, AddressOf FormClosing 
     End Sub 

     Private Shared Sub FormClosing(sender As Object, e As FormClosingEventArgs) 
      If e.CloseReason = CloseReason.UserClosing Then 
       e.Cancel = True 
       _inst.Hide() 
      Else 
       _inst = Nothing 
      End If 
     End Sub 

    End Class 

End Module 

и называть его просто так:

frmMain.GetInstance().Show() 
Form1.GetInstance().Show() 
Form1.GetInstance().Hide() 
Form2.GetInstance().ShowDialog() 
Смежные вопросы