2012年10月28日日曜日

[C#] Func デリゲート

ラムダ式を書くときにインテリセンスで見かけるFunc型。
C#で定義済みのデリゲートらしい。

■そもそもデリゲートの定義
http://ufcpp.net/study/csharp/sp_delegate.html#definition

■Funcデリゲート
http://msdn.microsoft.com/ja-jp/library/vstudio/bb549151.aspx


Func<T, TResult>

っていう型の引数があったら

「T型の引数を取ってTResult型の戻り値を返すデリゲート」

を渡せばよい事になる。なんのこっちゃ。


Funcデリゲートを引数に取るメソッドを作ってみる。


        public void Test()
        {
            // ラムダ式で匿名メソッドのデリゲートを渡す。

            // (ここではmsg を引数に取り、それに文字列を足したものを戻り値とする)
            string result1 = funcTest(msg => { return msg + "1"; });
            string result2 =
funcTest(msg => { return msg + "2"; });

            Console.WriteLine(result1);
            Console.WriteLine(result2);
        }

        private string
funcTest(Func<string, string> method)
        {
            return method("ほげほげ");
        }




■実行結果
ほげほげ1
ほげほげ2


なんというか、ぴんとこない。まあいいや。


Func(T1, T2, TResult)だとかFunc(T1, T2, T3, TResult)だとか
引数の数を増やしただけのオーバーロードがたくさんあるようだ。



■よく見かける(ような気がする)定義済みのデリゲート、メモ

Predicate<in T>
T型の引数を取ってboolを返す
http://msdn.microsoft.com/ja-jp/library/vstudio/bfcke1bz.aspx

Action<in T>
T型の引数を取って戻り値を返さない
http://msdn.microsoft.com/ja-jp/library/vstudio/018hxwa8.aspx

VsVim

http://visualstudiogallery.msdn.microsoft.com/59ca71b3-a4a3-46ca-8fe1-0e90e3f79329

VisualStudioにVsVimを入れる → VIでコーディングがはかどる → 最強

※効果には個人差があります

2012年10月20日土曜日

[ASP.NET MVC] WebGrid のページング(2)

参考サイト
http://msdn.microsoft.com/ja-jp/magazine/hh288075.aspx

サーバー側のページ切り替えをやってみるテスト。
表示に必要なデータだけをDBから取得する。そしてWebGridでページングする。

■サーバー側のデータ取得(コントローラー)

        /// <summary>
        /// ページングのテスト
        /// </summary>
        /// <returns></returns>
        public ActionResult Paging(int? page)
        {

            // page は WebGrid が生成するページングリンクのURLに
            // GETパラメータとして指定されている
            return View( new PaginatedList<SchoolViewModel>( 

                              getData() , (page != null ? (int)page - 1: 0) , 3 )
            );
        }

        /// <summary>
        /// データを取得します
        /// </summary>
        /// <returns></returns>
        private IQueryable<SchoolViewModel> getData()
        {
            Models.hogeEntities db = new Models.hogeEntities();
            return
                (from sc in db.SchoolClass
                 join s in db.Schooler
                 on sc.ClassID equals s.ClassID
                 orderby sc.Grade, sc.Class
                 select new SchoolViewModel()
                 {
                     Grade = sc.Grade
                    ,
                     Class = sc.Class
                    ,
                     name = s.Name
                 });
        }



ここ↓のPaginatedListというクラスをそのまま流用している
http://www.atmarkit.co.jp/fdotnet/scottgublog/nerddinner/part08.html

■PaginatedList

    public class PaginatedList<T> : List<T>
    {

        public int PageIndex { get; private set; }
        public int PageSize { get; private set; }
        public int TotalCount { get; private set; }
        public int TotalPages { get; private set; }

        public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize)
        {
            PageIndex = pageIndex;
            PageSize = pageSize;
            TotalCount = source.Count();
            TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);

            this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
        }

        public bool HasPreviousPage
        {
            get
            {
                return (PageIndex > 0);
            }
        }

        public bool HasNextPage
        {
            get
            {
                return (PageIndex + 1 < TotalPages);
            }
        }
    }



コンストラクタでIQueryableのデータをSkip&Takeして、PageIndexに該当するデータを取得してる。



■chtml

@model MvcApplication1.Models.PaginatedList<MvcApplication1.Models.SchoolViewModel>

@{
    ViewBag.Title = "Paging";
    Layout = "~/Views/Shared/_Layout.cshtml";

    // WebGridオブジェクト生成
    var grid = new WebGrid(null, rowsPerPage: Model.PageSize);
    grid.Bind(Model, rowCount: Model.TotalCount, autoSortAndPage: false);
}

<h2>Paging</h2>

@* WebGridオブジェクトでレンダリング *@
@grid.GetHtml(columns:grid.Columns(
grid.Column("Class","クラス", canSort:false)
    ,grid.Column("Grade", "学年", canSort:false)
    ,grid.Column("Name", "名前", canSort:false)
    )
)


ポイントっぽいところ
・WebGridのコンストラクタで source にnullを指定する
・Bindメソッドでページの表示に必要なデータと全体の件数を渡し、autoSortAndPage を false にする
(autoSortAndPage を false にするとデフォルトのソート機能も無効になる)






WebGridにページに表示する分のデータしか渡してないけど
ちゃんとページングのリンクを生成してくれている。

2012年10月14日日曜日

[ASP.NET MVC] WebGrid のページング

WebGridはデータを表形式で表示してくれるRazor ヘルパー。
(ASP.NET WebForms の GridView のようなものと理解している)

ページングが簡単にできるのがいいと思った。

chtmlファイルのおれおれサンプル


@model IList<MvcApplication1.Models.SchoolViewModel>

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";

    // WebGridオブジェクト生成
    var grid = new WebGrid(source:Model, rowsPerPage: 3);
}

<h2>Index</h2>

@* WebGridオブジェクトでレンダリング *@

@grid.GetHtml(
columns: grid.Columns(
grid.Column("Grade", "学年")
, grid.Column("Class", "クラス")
, grid.Column("Name", "名前")
    )
)


WebGridオブジェクトのコンストラクタに rowsPerPage(1ページに表示するデータ数)を
指定するとページングできるようになる。
WebGridが生成するページングのリンクURLにはGETパラメータが付加されていて
それによって現在のページを把握しているようだ。



※表の見た目等はGetHtml()の引数で変えられる


WebGridにソースとして100件のデータを渡しても
例えば1ページ10件ごとの設定なら当然ながら10件分のデータしか表示されない。

実際ページの表示に使うデータだけをDBから取得して
WebGridでページングを行うにはどうすればよいのか?
下記のサイトにやり方が書いてあるっぽい。
http://msdn.microsoft.com/ja-jp/magazine/hh288075.aspx



でも今日は疲れたのでまた今度やる!(ヘタレ)

Razorって…なに?

Razor 構文とは?
http://msdn.microsoft.com/ja-jp/asp.net/hh182563.aspx

> 従来の ASPX や PHP よりも少ないコード量やタイプ量で軽快に動的な Web ページを記述することができます。

要するにASPXより楽できるんですか。

2012年10月6日土曜日

[C#] コンストラクタ初期化子

コンストラクタってこんな書き方できるんだ…。初期値を指定できるのね。


    public class Hoge
    {
        public string Foo { get; set; }
       
        public Hoge() : this("だれか")
        {
        }

        public Hoge(string foo)
        {
            this.Foo = foo;
        }
    }


WindowsServer2003でW3SVCサービスを再起動せずに仮想ディレクトリの.NET Frameworkのバージョンを変更する方法

長いタイトル。

仮想ディレクトリの.NET Frameworkのバージョンを2→4に上げようとしたら

Framework バージョンを変更するには W3SVC サービスを再起動する必要があります。

などとというメッセージが出た。ええいやってしまえ!と再起動したかったけど、本番サーバーなのでそうもいかず。


W3SVCを再起動せずにバージョンを変更するには aspnet_regiis.exe を使うらしい。

たぶんここ↓で調べた(昔のメモなのでよく覚えてない)
http://stackoverflow.com/questions/1804208/how-do-you-work-out-the-iis-virtual-path-for-an-application


.NET Framework4の aspnet_regiis.exe は下記のフォルダにあった。
C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319


■手順

1.-lk オプションでIIS上のパスを調べる。
aspnet_regiis.exe -lk

MSDNによると -lk オプションは

ASP.NET が割り当てられている、すべての IIS メタベース キーのパスとバージョンを一覧表示します。

 フーン( ´_ゝ`)


実行するとこんなの↓が一覧でずらずら出てくる
W3SVC/<数値>/ROOT/<アプリケーション名>/


2.-s と -norestart オプションに 1. で調べたパスをつけて設定完了
aspnet_regiis.exe -norestart -s "W3SVC/<数値>/ROOT/<アプリケーション名>/"

MSDNによると -s オプションは

Aspnet_regiis.exe に関連付けられた ASP.NET ISAPI バージョンをポイントするスクリプト マップを、指定したアプリケーション ルート パスとそのサブディレクトリ内のすべての ASP.NET アプリケーションにインストールします。ASP.NET ISAPI の以前のバージョンを使用する、指定したパス以下にある既存のスクリプト マップは、すべて更新されます。

なるほどよくわからない!

実行したらちゃんとバージョン変ってたのでよしとする!(それでいいのか)