none
ViewStateのラッパークラス作成について RRS feed

  • 質問

  •  

    ViewStateのラッパークラスを作成したいのですが、どう記述したら良いか悩んでおります。

     

    Sessionだと下記の感じなのですが、ViewStateの場合はどうしたら良いのでしょうか。

    ご教示願います。

     

        public class DataSession
        {

            public Object this[String strValue]
            {
                get  {return HttpContext.Current.Session[strValue];}
                set  {HttpContext.Current.Session[strValue] = value;}
            }
            public Object this[Int intValue]
            {
                get  {return HttpContext.Current.Session[intValue];}
                set  {HttpContext.Current.Session[intValue] = value;}
            }

        }

     

     

    2007年8月23日 6:47

回答


  • そこで、恐縮なのですが、技術的に可能なのかどうかをご教示頂けますか。
    後学の為に知りたいと考えています。

    あ、すみません。質問に全く答えていない事に今気付きました。質問に答えていないのにグダグダ言ってもしょうがありませんよね。

     

    Session のようにはいきません。

     

    Page.Session は単に HttpContext.Current.Session を参照しているだけですが、
    先述したように ViewState はあくまで Page のデータです。
    さらに、ViewState は protected なので以下のようにもできません。

     

    Code Snippet

    public class DataViewState{
        private Page _page;

        public DateViewState(Page page){
            _page = page;
        }

        public string Hoge{
            get{ return (string)_page.ViewState["Hoge"]; }
        }
    }

     

     

    という事で無理です。

     

    2007年9月18日 5:39
  •  marumusisan さんからの引用

            public Object this[String strKey]
            {
                get
                {
                    object o = ViewState[strKey];
                    return (o == null)? String.Empty : (string)o;

                }
                set
                {
                    ViewState[strKey] = value;
                }
            }

    たとえコンパイル通っても無意味だと思います。ラップになっていません。

     

    #インデクサでしたか…プロパティにするのかと思ってました。

     

    プロパティにするなら先ほど書いた

    StateBag クラス

    http://msdn2.microsoft.com/ja-jp/library/system.web.ui.statebag(VS.80).aspx

    のサンプルのようにするのではダメでしょうか。

     

    ViewState はページ固有のデータなので、他からアクセスすることは考えられないので、やはり囚人様が仰せになるとおり、Session プロパティや ViewState プロパティに直接アクセスするのがいいと思います。

     

    方法 : ビューステートから値を読み取る
    http://msdn2.microsoft.com/ja-jp/library/ms228048(VS.80).aspx
    方法 : ビューステートに値を保存する
    http://msdn2.microsoft.com/ja-jp/library/ms227551(VS.80).aspx

    先ほど書きましたとおり、

    キー文字列の方を共有で使用するクラスに定数としてまとめれば、入力ミス防止やIntelliSenseで入力補助ができると思います。

    2007年9月18日 5:42
  • イメージ的には以下のような感じですよね?

     

    public partial class ViewStateTest : System.Web.UI.Page

    {

        DataSession dsession;

     

        protected void Page_Load(object sender, EventArgs e)

        {

            dsession = new DataSession();

            this.Controls.Add(dsession);

        }

     

        protected void cbtn_save_Click(object sender, EventArgs e)

        {

            dsession["test"] = TextBox1.Text;

        }

     

        protected void cbtn_load_Click(object sender, EventArgs e)

        {

            Label1.Text = (string)dsession["test"];

        }

    }

     

     

    public class DataSession : Control

    {

        public Object this[string strValue]

        {

            get { return this.ViewState[strValue]; }

            set { this.ViewState[strValue] = value; }

        }

     

    }

     

    ViewStateはコントロールが対象なので、やろうと思えば上のような感じになると思いますが、提示されたSessionのラップクラスを含め、セマンティクス的には意味が無いように思えます。

     

    #(追記)ただ、用途によっては意味があるかもしれません・・・

    2007年9月18日 5:54
    モデレータ

すべての返信

  • なかなか光が見えてきませんが・・・

     

    やはり例えば以下の様に、地道にプロパティを記述するしかないのでしょうか

     

    よろしくお願いします。

     

      public int Counter
      {
        get
        {
          object objCounter = ViewState["btnCounter"];
          int CounterClick = 0;
          if (objCounter != null)
            CounterClick = (int)objCounter;
          return CounterClick;
        }
        set
        {
          ViewState["btnCounter"] = value;
        }
      }

    2007年9月18日 0:41
  • 何故ラッパークラスを作りたいんでしょう?ViewState プロパティをそのまま使っても良いと思いますけど。

     

    ご提示の通りプロパティでラップするというのもアリだと思いますよ。何に困っているのかがよくわかりません。
    2007年9月18日 2:33
  • 返信ありがとうございます。

     

    正直困っているわけではありませんが、チームで開発時に

    System.Web.UI.Pageを継承したスーパークラスを作成する事はよくあると思いますが、

    その際にSessionやFormデータ等いろいろと格納するケースがあると思われます。

     

    コードセーフ目的とアクセスの容易性(まぁEXCELとかに一覧作っても良いのですが)を目的としています。

     

    そんなわけです。又個人的な興味という点もございます。

     

    よろしくお願いします。

    2007年9月18日 2:50
  •  marumusisan さんからの引用

    System.Web.UI.Pageを継承したスーパークラスを作成する事はよくあると思いますが、

    その際にSessionやFormデータ等いろいろと格納するケースがあると思われます。

     

    ViewStateでも最初のご投稿でSessionについて書かれてるようにすればよいのではないでしょうか。

     

    MSDNライブラリの以下のページのサンプルにもそれと似てるのがありますし。

    StateBag クラス

    http://msdn2.microsoft.com/ja-jp/library/system.web.ui.statebag(VS.80).aspx

     

    別の方法として使用するキーの文字列の方を共有で使用するクラスに定数としてまとめるとかどうでしょうか。
    2007年9月18日 3:54
  • アドバイスありがとうございます。

     

    確かにおっしゃる通りなのですが

            public Object this[String strKey]
            {
                get
                {
                    object o = ViewState[strKey];
                    return (o == null)? String.Empty : (string)o;

                }
                set
                {
                    ViewState[strKey] = value;
                }
            }

     

    こんな感じでコード書いてもコンパイルが通るはずもなく・・・

     

    エラー 598 名前 'ViewState' は現在のコンテキスト内に存在しません。

     

    私が理解できていないのが原因なのですけど。

     

    良きアドバイス頂ければ幸いです。

    2007年9月18日 4:12
  • ViewState というのはリクエストされたページに「固有のデータ」ですよね。データをクラスにしてしまおうという設計はちょっと変じゃないでしょうか。個人的には Session もそのようにクラスでラップするのは扱いづらいです。


    例えば、marumusisan さんが言うようにスーパークラスに ViewState のプロパティを定義したとしましょう。
    この場合、単に「同じ名前のビューステート」であって「同じビューステート値」ではないですよね?各々のページで値は違います。


    同じようにスーパークラスにセッションのプロパティを定義したとしましょう。
    この場合、全てのページで「同じ名前のセッション」であり、且つ「同じセッション値」になります。


    ビューステートやセッションはそういうものだから混乱しないですが、クラスやプロパティでラップしてしまうとビューステートやセッションである事が隠されてしまい混乱の元になるでしょう。折角ラップしても、ビューステートなのかセッションなのかをいちいち意識していないといけません。


    という事で、私はせいぜい private なプロパティにラップするに留めるか、そのまま Session プロパティや ViewState プロパティに直接アクセスする(インデクサの文字列は定数にしていても良い)事が望ましいと思います。

    2007年9月18日 4:42
  • 返信ありがとうございます。

     

    おっしゃる通りであると、私も思います。

     

    そこで、恐縮なのですが、技術的に可能なのかどうかをご教示頂けますか。

    後学の為に知りたいと考えています。

     

    2007年9月18日 5:20

  • そこで、恐縮なのですが、技術的に可能なのかどうかをご教示頂けますか。
    後学の為に知りたいと考えています。

    あ、すみません。質問に全く答えていない事に今気付きました。質問に答えていないのにグダグダ言ってもしょうがありませんよね。

     

    Session のようにはいきません。

     

    Page.Session は単に HttpContext.Current.Session を参照しているだけですが、
    先述したように ViewState はあくまで Page のデータです。
    さらに、ViewState は protected なので以下のようにもできません。

     

    Code Snippet

    public class DataViewState{
        private Page _page;

        public DateViewState(Page page){
            _page = page;
        }

        public string Hoge{
            get{ return (string)_page.ViewState["Hoge"]; }
        }
    }

     

     

    という事で無理です。

     

    2007年9月18日 5:39
  •  marumusisan さんからの引用

            public Object this[String strKey]
            {
                get
                {
                    object o = ViewState[strKey];
                    return (o == null)? String.Empty : (string)o;

                }
                set
                {
                    ViewState[strKey] = value;
                }
            }

    たとえコンパイル通っても無意味だと思います。ラップになっていません。

     

    #インデクサでしたか…プロパティにするのかと思ってました。

     

    プロパティにするなら先ほど書いた

    StateBag クラス

    http://msdn2.microsoft.com/ja-jp/library/system.web.ui.statebag(VS.80).aspx

    のサンプルのようにするのではダメでしょうか。

     

    ViewState はページ固有のデータなので、他からアクセスすることは考えられないので、やはり囚人様が仰せになるとおり、Session プロパティや ViewState プロパティに直接アクセスするのがいいと思います。

     

    方法 : ビューステートから値を読み取る
    http://msdn2.microsoft.com/ja-jp/library/ms228048(VS.80).aspx
    方法 : ビューステートに値を保存する
    http://msdn2.microsoft.com/ja-jp/library/ms227551(VS.80).aspx

    先ほど書きましたとおり、

    キー文字列の方を共有で使用するクラスに定数としてまとめれば、入力ミス防止やIntelliSenseで入力補助ができると思います。

    2007年9月18日 5:42
  • ありがとうございます。

     

    ViewStateについては、インデクサではくプロパティにて実装するしかないんでしょうね・・・

     

    ViewStateの性質からも、そうなんでしょうね。勉強になりましたありがとうございます。

     

    2007年9月18日 5:50
  • イメージ的には以下のような感じですよね?

     

    public partial class ViewStateTest : System.Web.UI.Page

    {

        DataSession dsession;

     

        protected void Page_Load(object sender, EventArgs e)

        {

            dsession = new DataSession();

            this.Controls.Add(dsession);

        }

     

        protected void cbtn_save_Click(object sender, EventArgs e)

        {

            dsession["test"] = TextBox1.Text;

        }

     

        protected void cbtn_load_Click(object sender, EventArgs e)

        {

            Label1.Text = (string)dsession["test"];

        }

    }

     

     

    public class DataSession : Control

    {

        public Object this[string strValue]

        {

            get { return this.ViewState[strValue]; }

            set { this.ViewState[strValue] = value; }

        }

     

    }

     

    ViewStateはコントロールが対象なので、やろうと思えば上のような感じになると思いますが、提示されたSessionのラップクラスを含め、セマンティクス的には意味が無いように思えます。

     

    #(追記)ただ、用途によっては意味があるかもしれません・・・

    2007年9月18日 5:54
    モデレータ
  • ありがとうございます。

     

    どちらかといえば、コードの統一とコードセーフが目的ですので実装方法はどうでもよかったのですが、

    上記にある様にインデクサ形式では不可能のようでしたので、個人的な後学という観点から本スレッドは意味を持ちました。

     

    ありがとうございました。

    2007年9月18日 6:16
  • イメージ的にはと書いてしまったので、動かないコードと誤解されているかもしれないと思い、念のために書いておきます。
    marumusisanさんが思われているパターンとは違うかもしれませんが、上記コードでViewStateに読み書きできることを確認しています。

    2007年9月18日 7:29
    モデレータ
  • はい、ちょっと違いますが、そのパターンはまだコーディングした事がありませんので

    一回コーディングしてみます。

     

    いろいろと勉強になりました。

     

    ありがとうございます。

    2007年9月18日 7:38