none
Shared Property を正しく継承したい RRS feed

  • 質問

  • #問題の原因がまったく予測できていないため、表題がかなりおかしいですがお許しください。

    DOBONさんの http://dobon.net/vb/dotnet/form/singleform.html を参考にしながら規定の(単一の)フォームインスタンスを実装しようとしています。

    そこで質問なのですが、



    Public Class Form1
        Inherits Form
        Public Sub New()
            MyBase.New()
            Me.Text = "Form1ですよ"
        End Sub
        Protected Shared _instance As Form1
        Public Shared ReadOnly Property Instance() As Form1
            Get
                If _instance Is Nothing OrElse _instance.IsDisposed Then
                    _instance = New Form1
                End If
                Return _instance
            End Get
        End Property
    End Class
    Public Class Form2
        Inherits Form1
        Public Sub New()
            MyBase.New()
            Me.Text = "Form2ですよ"
        End Sub
        'このように動作してほしい
        'Protected Shared _instance As Form2
        'Public Shared ReadOnly Property Instance() As Form2
        '    Get
        '        If _instance Is Nothing OrElse _instance.IsDisposed Then
        '            _instance = New Form2
        '        End If
        '        Return _instance
        '    End Get
        'End Property
    End Class
    Public Class ClassMain
        Public Shared Sub Main()
            Form2.Instance.Show()
            MessageBox.Show("表示しました")
        End Sub
    End Class


     

    上記のように、規定の(単一の)フォームインスタンスを実装したForm1クラスを作成し、それを継承したForm2クラスなどでは規定の(単一の)フォームインスタンスを実装しなくてもいいように動作させたいのですがうまくいきません。(Form2.Instance.Show()ではForm1が表示されてしまいます。)

    何かうまい方法はあるのでしょうか?それとも各フォーム毎に、ほとんど同じような処理を実装しなくてはいけないのでしょうか?

    #code language="vb" タグ内でコメント" '(シングルクォーテーション) "を書くと、それ以降はすべてコメントと見なされるのかな?色がコメント色になってる・・・。

    2006年3月25日 1:40

すべての返信

  • Shared にしているわけですから、Form1を継承したすべてのもので、同じものを利用します。

    なので、無理です。

    2006年3月25日 5:42
  • _Instanceを クラス変数で持ってしまうと上手くないでしょうね

    _Instanceを Instanceプロパティ内のスタティック変数にして 継承クラスでShadowしてやればご希望の処理になりそうですよ

    Public Shared Shadows ReadOnly Property Instance() As Form1
         Get

             Static _Instance As Form
             if _Instance Is Nothing OrElse _Instance.IsDisposed then
                 _Instance = new Form1 ' 派生クラスなら Form2
             end if
         End Get
    End Property

    2006年3月25日 16:22
  • 返信ありがとうございます。

    >中博俊 さん

    >なので、無理です。

    やっぱり無理ですか・・・。

     

    >redfox63 さん

    なるほど、_Instanceをスタティック変数にすると変数自体は分かれそうですがInstanceプロパティ自体は個々のフォームで実装しなければいけないのですよね。この個々のフォームでの実装も止めてしまいたいのです。
    Instance()に何か引数を渡すなりして、要は New Form1 のForm1の部分を可変にしたいのですがうまくいきません。ジェネリクスなども、よく分からないまま見よう見まねで試してみたのですがうまくいきません。(ジェネリクスはこういうときに使用するものではないのかな?・・・)

    2006年3月27日 1:45
  •  コリン星人 さんからの引用

    要は New Form1 のForm1の部分を可変にしたいのですがうまくいきません。ジェネリクスなども、よく分からないまま見よう見まねで試してみたのですがうまくいきません。(ジェネリクスはこういうときに使用するものではないのかな?・・・)

    VB.NETは普段は全く書かないのですが、以下のような感じかしらん?
    ちなみにジェネリックはちと違います。



    Public _instance As Form

    Public ReadOnly Property Instance() As Form
        Get
            If _instance Is Nothing OrElse _instance.IsDisposed Then
                _instance = Me.GetType().Assembly.CreateInstance(Me.GetType().FullName)
            End If
            Return _instance
        End Get
    End Property

     

    2006年3月27日 2:56
    モデレータ
  • 返信ありがとうございます。

    >trapemiya さん

    おお!すばらしい方法・・・と思ったらInstanceプロパティからシェ、シェ、Sheredが無くなってるぅ。できればSheredでお願いします。

    2006年3月27日 10:25
  • miya さんのプロパティ変数が Public になってる...w
    名前も CLS 違反になっちゃったり。(;^-^)

    2006年3月27日 10:31
  • すみません、みなさま。(^^;;;;;



    Protected Shared _Instance As Form

    Public Shared Function InstanceForm(ByVal str As String) As Form
        If _Instance Is Nothing OrElse _Instance.IsDisposed Then
            _Instance = Activator.CreateInstance(Type.GetType(str))
        End If
        Return _Instance
    End Function

    としておいて、

    Form2.InstanceForm("名前空間.Form2").Show()

     

    (追記編集)コード削除しました。何かできそうなんですけどね・・・
    (追記編集)とりあえず夜も遅いので、ごまかしコード掲載(^^;

    2006年3月27日 11:58
    モデレータ
  • AOPっぽいところですな。

    ちなみにVB8の実装を知りませんが、同じことをするために、Form毎に用意しているはずです。

    2006年3月27日 14:41
  • >trapemiya さん

    度々のサンプルコードありがとうございます。
    このコードを基にもう少し考えて自分でも考えてみることにします。

    >中博俊 さん

    同じことをするために、Form毎に用意しているはずです。

    やはりそういうことになりますか。

    2006年3月28日 9:49
  • こんにちは。

    以下のように、HashTableを使用してはいかがでしょうか?



        Protected Shared _instance As New Hashtable

        Public Shared Function getInstance(ByVal value As String) As Form

            If _instance.ContainsKey(value) Then
                If _instance.Item(value) Is Nothing OrElse _instance.Item(value).IsDisposed Then
                    _instance.Remove(value)
                    _instance.Add(value, System.Activator.CreateInstance(Type.GetType(value)))
                End If
            Else
                _instance.Add(value, System.Activator.CreateInstance(Type.GetType(value)))
            End If

            Return CType(_instance.Item(value), Form)

        End Functions

     

     

    2006年3月29日 8:22
  • >Guvava13 さん

    おお!このコード良さげです。
    Hashtableのおかげでクラス毎にきちんとインスタンスが分かれていますし、ほぼ希望通りです。
    頂くことにさせていただきます。
    ありがとうございました。

    2006年3月29日 10:06
  • 引数渡すのOKなんだ・・・(^^;;;;
    2006年3月29日 11:07
  • 引数渡すのOKなんだ・・・

    そりゃ、本音は引数を渡したくないです。上のレスで”ほぼ”と書いたのはその部分(引数を渡す部分)があったからです。

    もし引数を渡さなくてもいい方法があれば引き続き情報を求めます。

    2006年3月29日 11:34