プログラミング C# - 翔ソフトウェア (Sho's)

C#/.NET/ソフトウェア開発など

「富山合同勉強会 .NET & Java - MVP Community Camp 2015 北陸会場 -」が開催されました

※ 「MVP Community Camp 2015 (2015年1月31日) ~北陸は富山でやります~」の続き。

1月31日に、「富山合同勉強会 .NET & Java - MVP Community Camp 2015 北陸会場 -」が開催されました。

資料を公開します。

.NET MVP によるドキドキ・ライブコーディング! 小島の分 (アニメーションが有効な slideboom 版)

MVP Community Camp 2015 リンク

MVP Community Camp 2015 北陸会場について

富山県の旅館の 2 つの部屋で、それぞれ .NETJava のセッションが行われました。

懇親会では、寒ブリのしゃぶしゃぶなどが楽しまれました。

富山合同勉強会 .NET & Java - MVP Community Camp 2015 北陸会場 -
会期 2015年1月31日(土)
会場 富山県 呉羽ハイツ
主催 Hokuriku.NET
北陸エンジニアグループ
協力 日本マイクロソフト

会場の様子

「富山ぶりしゃぶ勉強会へようこそ!」
「富山ぶりしゃぶ勉強会へようこそ!」
Hokuriku.NET のロゴ ステッカーと Microsoft MVP 飴、Microsoft
Hokuriku.NET のロゴ ステッカーと Microsoft MVP 飴、Microsoft 飴
セッションの様子
セッションの様子
懇親会の様子
懇親会の様子

他の方の発表資料

関連記事

MVP Community Camp 2015 (2015年1月31日) ~北陸は富山でやります~

MVP Community Camp

MVP Community Camp 2015

MVP Community Camp がアジア パシフィック地域で開催されています。

今年 (2015年) の 1 月 31 日は全国 8 箇所で、オフラインの勉強会が開催されます。

MVP Community Camp 2015 北陸会場

北陸は、今年は富山での開催です。

今回は、.NET と Java の合同勉強会となっており、 2つの部屋にて、それぞれのセッションが同時進行されます。

.NET 側が MVP Community Camp 2015 北陸会場となります。

同じ会場で、絶品寒ブリのしゃぶしゃぶなどを楽しめる懇親会も開催され、その後の宿泊も可能です。温泉もあります。

是非ご参加ください。

富山合同勉強会 .NET & Java - MVP Community Camp 2015 北陸会場 -
会期 2015年1月31日(土)
会場 富山県 呉羽ハイツ
参加費 無料
主催 Hokuriku.NET
北陸エンジニアグループ
協力 日本マイクロソフト
詳細/お申込み 富山合同勉強会 .NET & Java - MVP Community Camp 2015 北陸会場 | connpass
MVP Community Camp 2015 北陸会場 リーフレット

豪華講師陣などの詳しい内容が確認できる MVP Community Camp 2015 北陸会場の リーフレットがダウンロードできます (PDF): こちら

参考: 昨年までのイベント

2015年1月版 小学生と楽しめるボードゲーム/カードゲームに寄せられたお勧め作品

SNS で次のように呟いたところ、

「ようやく娘たちがボードゲーム/カードゲームを楽しむ年齢になってきたようだ。
小学生あたりが短時間でさっと楽しめるボードゲーム/カードゲームってどういうのがあるのかな。
知人に詳しい人がいればなー。」

ありがたくも、多くの人がアドバイスをくださり、知人にボードゲーム/カードゲーム ファンが結構多かったことが分かった。

折角なので、まとめてみた (アドバイスの順)。

見るからに面白そうなゲームが沢山あって、どれから買おうか、迷うのも楽しい。

 タイトル原題お寄せいただいたお勧めポイント発売高円寺0分すごろくやAmazon.co.jp
メーカー発売年ゲーム紹介ページ年齢プレイ人数所要時間ルール難度ページ参考価格補足
ニムト
ニムト 6 nimmt! お手軽系 ドイツ AMIGO (アミーゴ) 1994年 ニムト / 6 nimmt 8才~大人 2~10人 5分 1.5 メビウス ニムト ¥1,200   ドイツ 1994年 ゲーム大賞 準候補
ゲシェンク
ゲシェンク Geschenkt お手軽系 ドイツ AMIGO (アミーゴ) 2011年
(原版 2004年)
ゲシェンク / Geschenkt 8才~大人 3~7人 20分 1.5 ゲシェンク日本語版 (Geschenkt) / Amigo・メビウスゲームズ / Thorsten Gimmler ¥1,500   ドイツ 2005年 ゲーム大賞 準候補
キングダム
キングダム Kingdoms お手軽系 アメリカ Fantasy Flight (ファンタジーフライト) 2011年 キングダム / Kingdoms 14才~大人 2~4人 20〜40分 1.5 キングダム 完全日本語版      
すすめコブタくん
すすめコブタくん Rüsselbande 短時間 ドイツ Drei Magier Spiele (ドライマギア社) 2001年 すすめコブタくん / Rüsselbande 4才~大人 2~7人 (推奨4人以上) 20分 1.5 Drei Magier すすめコブタくん (こぶたのレインボーレース) ¥4,536 箱寸法:22.5×22.5×5cm ドイツ 2001年 キッズゲーム大賞 最終候補
Drei Magier すすめコブタくんミニ(ミニこぶたのレインボーレース) ¥2,680 箱寸法:14.7×14.7×4cm
あやつり人形
あやつり人形 Citadels お気に入り アメリカ Fantasy Flight (ファンタジー・フライト) 2009年
(原版 2000年)
あやつり人形 (拡張同梱, 日本語版) 10才~大人 2~7人 60~90分 2 あやつり人形 完全日本語版 ¥2,590 + ¥500 関東への配送料   ドイツ 2000年 ゲーム大賞 最終候補
エルフェンランド
エルフェンランド Elfenland そろそろ行けそう。でもプレイ時間がちょっと長いかもしれない ドイツ AMIGO (アミーゴ) 2013年
(原版 1998年)
エルフェンランド / Elfenland 10才~大人 2~6人 60分 2 Elfenland: AMIGO - Familien- und Gesellschaftsspiel ¥3,800   ドイツ 1998年 ゲーム大賞 大賞受賞
キャプテン・リノ
キャプテン・リノ Super Rhino! 立体 (UNO 的) カードゲーム ドイツ HABA (ハバ) 2010年 キャプテン・リノ / Super Rhino! 5才~大人 2~5人 10分 1.5 キャプテン・リノ (日本版) ¥1,720 + ¥500 関東への配送料   ドイツ 2012年 キッズゲーム大賞 準候補
ラビリンス
ラビリンス Das verrückte Labyrinth 初心者でも遊べて、親も楽しい系。
思わぬ展開。ボード
ドイツ Ravensburger (ラベンスバーガー) 1986年 ラビリンス / Das verrückte Labyrinth 7才~大人 2~4人 30分 1.5 Ravensburger ラビリンス ¥2,745   ドイツ 1986年 ゲーム大賞 候補
呪いのミイラ
呪いのミイラ Fluch der Mumie 初心者でも遊べて、親も楽しい系。
一人 (父) 対 他 (娘)。対面ボード
ドイツ Ravensburger (ラベンスバーガー) 2008年 呪いのミイラ / Fluch der Mumie 8才~大人 3~5人 30分 1.5 呪いのミイラ (Fluch der Mumie)      
禁断の島
禁断の島 Forbidden Island 初心者でも遊べて、親も楽しい系。
協力ゲーム
アメリカ Gamewright (ゲームライト) 2010年 禁断の島 / Forbidden Island 10才~大人 2~4人 30分 2 禁断の島 (FORBIDDEN ISLAND) ¥4,940   ドイツ 2011年 ゲーム大賞 大賞受賞 最終候補
ぴっぐテン
ぴっぐテン Pig 10 初心者でも遊べて、親も楽しい系。
足し算カードゲーム
ドイツ Zoch (ツォッホ社) 2010年 ぴっぐテン / Pig 10 6才~大人 2~8人 15~20分 1.5 ぴっぐテン 日本語版 ¥1,500    
百人一首
百人一首   ちはやふるの漫画全巻と一緒に 日本               任天堂 百人一首 舞扇 ¥930 + ¥514 関東への配送料    
ラブレター
ラブレター Love Letter ものの5分でケリのつく、運と推理
# なので"3点先取"なカンジで遊びます。
女の子には「ラブレター」いいかもですねー、ロマンチックで。
# 同梱されてる拡張カードで、ラブレターを渡す相手を"姫"から"王子"に差し替えられますし♪
日本 アークライト 2014年
(原版 2012年)
ラブレター (2014年箱版) / Love Letter 10才~大人 2~4人 10分 1.5 ラブレター ¥2,550 + ¥648 関東への配送料    
ハゲタカのえじき
ハゲタカのえじき Hol's der Geier わかりやすさでいけば イスラエル kodkod (コドコド) 2011年
(原版 1988年)
ハゲタカのえじき / Hol's der Geier 8才~大人 2〜6人 20分 1.5 カードゲーム ハゲタカのえじき 日本語版 ¥1,500   ドイツ 1988年 ゲーム大賞 候補
ごきぶりポーカー
ごきぶりポーカー Kakerlakenpoker 騙し合いの応酬 ドイツ Drei Magier (ドライ マギア) 2004年 ごきぶりポーカー / Kakerlakenpoker 8才~大人 2~6人 20分 1.5 メビウス ごきぶりポーカー ¥1,800   ドイツ 2004年 ゲーム大賞 準候補
ドブル
ドブル Dobble どんちゃん騒ぎ系
# 子供の方が強いと思う...
フランス Asmodee (アスモデ) 2011年
(原版 2009年)
ドブル (スポットイット) / Dobble 7才~大人 2~8人 20分 1 ドブル      
キング・オブ・トーキョー
キング・オブ・トーキョー King of Tokyo 男の子にはウケますよー
# ただしパンダ拡張は必須だと思います!
フランス IELLO (イェロ) 2011年 キング・オブ・トーキョー / King of Tokyo 8才~大人 2~6人 30分 1.5 キング・オブ・トーキョー 日本語版 ¥8,100    
キング・オブ・トーキョー パワーアップ 日本語版 ¥1,900 キング・オブ・トーキョー パワーアップ (パンダ拡張)  
ディクシット
ディクシット Dixit 子供向けなら、Dixit がオススメです。 フランス Libellud (リベリュー) 2008年 ディクシット / Dixit 8才~大人 3~6人 30分 1.5 ディクシット 日本語版 ¥4,619   ドイツ 2010年 ゲーム大賞 大賞受賞
宝石の煌き
宝石の煌き Splendor もし、もっとやりごたえのあるゲームを求めてらっしゃるなら、女の子の目がキラキラ輝くゲーム「宝石の煌き」もおススメです。こちらも昨年のドイツ年間ゲーム大賞にノミネートされた作品で、自分としては昨年のベストだと思っているゲームです。我が家でもファミリーゲームや友人と勝負するゲームとして幅広く活躍しています。
宝石の煌き (Splendor) - 部屋とボードゲームと私と酒と泪と男と女
フランス SPACE Cowboys 2014年   10歳以上 2~4人 30分 1 宝石の煌き (Splendor) ¥4,850   ドイツ 2014年 ゲーム大賞 最終候補
アラカルト
アラカルト A la carte ギミックを楽しむなら、アラカルト。お料理ままごとセットが丸ごとついてくる凝ったゲーム。サイコロ降ったり、スパイス振ったりで、思ったように作れない所がミソ。部品にコストがかかりすぎ、再販はないだろうと言われているので、入手するなら見つけた時に、と思ってます。 ドイツ Moskito Spiele (モスキート) 2010年
(原版 1989年)
アラカルト / A la carte 8才~大人 2~4人 30~45分 2 アラカルト ¥5,891   ドイツ 2010年 ゲーム大賞 最終候補
インカの黄金
インカの黄金 Incan Gold ヒカリモノ集めゲーなら アメリカ Gryphon Games (グリフォン) 2009年 (初版 2006年) インカの黄金 / Incan Gold 8才~大人 3~8人 30分 1.5 インカの黄金 完全日本語版 ¥2,504    
ナイアガラ
ナイアガラ Niagara ヒカリモノ集めゲーなら ドイツ Zoch (ツォッホ) 2005年 ナイアガラ / Niagara 8才~大人 3~5人 45分 2.5 ナイアガラ NIAGARA Zoch 社 日本語ルール付属 ドイツゲーム大賞受賞作 [並行輸入品] ¥10,900   ドイツ 2005年 ゲーム大賞 大賞受賞
エンパイア ビルダー
エンパイア ビルダー Empire Builder 中学にあがったら、おばちゃんが Empire Builder というすっごく面白いゲームを教えてあげようw<偉そう&シリーズ多数で極悪の道w アメリカ Mayfair Games (メイフェア ゲームズ) 1980年   12歳以上 2~6人 180分          
酋長ボンバボン
酋長ボンバボン Häuptling Bumm-Ba-Bumm   ドイツ HABA (ハバ) 2014年 酋長ボンバボン / Häuptling Bumm-Ba-Bumm 6才~大人 3~5人 10〜15分 1.5        
ガイスター
ガイスター Geister お子様向けなら、基本 イスラエル KODKOD (コドコド) 2012年
(初版 1982年)
ガイスター / Geister 10才~大人 2人専用 10~20分 1.5 Geisterガイスター (日本語版2012新版) ¥2,800    
お化け屋敷ゲーム
お化け屋敷ゲーム   日本が誇る「お化け屋敷ゲーム」も夏休みの定番 日本 バンダイ             絶叫! おばけ屋敷ゲーム ¥1,750    
キャット & チョコレート
キャット & チョコレート Cat & Chocolate 老若男女コミュニケーションゲーw 日本 cosaic (コザイク) 2012年
(原版 2010年)
キャット & チョコレート / Cat & Chocolate 8才~大人 3~6人 20分 1.5 キャット & チョコレート      

※ 「カタン」、「カルカソンヌ」、「ドミニオン」に関しては、私が既に持っていて最近娘たちと楽しんでいる旨を SNS に上げていた。

マイクロソフト キャンペーンの「C丼」を作って実食してみた

C丼キャンペーン

マイクロソフト「C丼キャンペーン」というのを始めようとしているようだ。

手元に C丼のストラップがある。

C丼ストラップ
C丼ストラップ

プログラミング言語 C# (シーシャープ) の "#" の文字は実は、井桁 (number sign: 番号記号) であり、♯ (sharp、嬰記号) ではない、というのは有名だが、こちらは丼だ。

それって美味しいの?

ところで、IT 技術者というのは、「それって美味しいの?」という台詞をよく口にする。

エンジニアリングでは、理論的なことはともかく、「それは実際にモノづくりの役に立つのか?」を追求する。 エンジニアは、「それは美味しいのか (実践的に役立つのか)? 」を気にするのだ。

「C丼」? それって美味しいのか?

実際に作って食べてみることにした。

C丼を作って実食しよう

「C丼」部分は色から考えて、ニンジンで作るのが良いだろう。

包丁と細かい作業が出来る刃物を用意。

ニンジンを切って「C丼」部分を作る
ニンジンを切って「C丼」部分を作る

できた。曲線部分や丼の井のところが難しいかと思ったが、割と簡単だった。

細工が完成した「C丼」部分 (※ ニンジンの残りの部分は、スタッフが美味しくいただきました)
細工が完成した「C丼」部分

これを、出汁醤油で煮てみる。

煮られる「C丼」部分
煮られる「C丼」部分

煮物は冷めるときに味がしみ込む。

味がしみ込みつつある「C丼」部分
味がしみ込みつつある「C丼」部分

さて、ご飯を用意しよう。

件のストラップを再度確認しよう。

何やら解説が書いてある。

XAML: ザーサイ&ナムル」? 「RICE: Rich Imagination Construction Engine」?

ちょっと何言ってるか分からないが、ともかく真似してみよう。

にご飯をよそう。

福井県産のコシヒカリだ。炊き立て。

丼によそわれたご飯
丼によそわれたご飯

そこに、ザーサイ&ナムルを半々にのせる。

ストラップではナムル部分がもっと緑だが、まあ良しとしよう。

ザーサイとナムルがのったご飯
ザーサイとナムルがのったご飯

その上に、「C丼」部分を飾れば完成だ!

完成した「C丼」
完成した「C丼」

さて食べよう。

「C丼」を食べよう
「C丼」の食べよう

これは!

そもそも「ダジャレ」ベースでデザインされた丼なので、全く期待していなかったが、うまいではないか。

ザーサイとナムルはご飯に合うし、一緒に食べてもうまい。

(ザーサイとナムルの味に思い切り依存するが)

「C丼」の実食
「C丼」の実食

完食!

「C丼」完食
「C丼」完食

結論

「C丼」は美味しい。お試しあれ。

IQueryable な Twitter のタイムライン クラスと LINQ プロバイダー

C#

C# Advent Calendar 2014」の12日目の記事。

前の記事 ← → 次の記事

以前、「[C#][式木][LINQ] Hokuriku.NET C# 勉強会『C# 式木』(2014-10-26、金沢) のスライド公開」で、IQueryable な LINQ について解説した。

  1. LINQ to Objects 復習
  2. IQueryable<T>
  3. 式木 (Expression Tree)
  4. 式木メタ プログラミング
  5. LINQ プロバイダー

本記事では、その中の IQueryable なサンプルを補足する。

IQueryable な LINQ の中はどのようになっているのだろうか。

試しに少し実装してみることで、LINQ について理解を深めよう。

IEnumerable と IQueryable

[C#][ラムダ式][LINQ][式木] 匿名メソッドとラムダ式の違い」で紹介したように、匿名メソッドdelegate としてしか使えないが、ラムダ式delegate としても式木としても使うことができる。

[C#][ラムダ式][式木] Expression として扱えるラムダ式と扱えないラムダ式」で紹介したように、ラムダ式であれば必ず式木として使うことができるわけではない。

※ クエリ構文は、「式木として扱えるラムダ式」の糖衣構文。つまり、式木を扱うことになる。

参考: LINQ でのクエリ構文とメソッド構文 (C#) - MSDN

LINQ の中には、次の二つの種類のライブラリがある。

  1. delegate を引数にしたもの
  2. 式木を引数にしたもの

LINQ to Objects などは前者で処理され、LINQ to SQLLINQ to Entities などは後者だ。

IQueryable なものを作ってみよう

今回は、IQueryable な Twitter のライムライン クラスを作ろうとしてみる。

先ずは IQueryable なクラス QueryableTweets。

※ IQueryable なだけでは OrderBy の対象となることができないので、ここでは IQueryable からの派生で OrderBy 可能な IOrderedQueryable を用いることにする。

// QueryableTweets.cs

using System.Linq;

// IOrderedQueryable<string> な QueryableTweets
// まだ IOrderedQueryable インタフェイスを実装してないのでコンパイル エラー
public class QueryableTweets<TElement> : IOrderedQueryable<TElement>
{}

ここから、Visual Studio でインタフェイスの実装を行うと次のようになる。

// QueryableTweets.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

// IOrderedQueryable<string> な QueryableTweets
// Visual Studio でインタフェイスを実装した直後
public class QueryableTweets<TElement> : IOrderedQueryable<TElement>
{
    public Type ElementType
    {
        get { throw new NotImplementedException(); }
    }

    public Expression Expression
    {
        get { throw new NotImplementedException(); }
    }

    public IQueryProvider Provider
    {
        get { throw new NotImplementedException(); }
    }

    public IEnumerator<TElement> GetEnumerator()
    { throw new NotImplementedException(); }

    IEnumerator IEnumerable.GetEnumerator()
    { throw new NotImplementedException(); }
}

IQueryable は IEumerable から派生している。そのため IEumerable のメンバーである GetEnumerator() を実装する必要がある。

その他に、ElementType、Expression、Provider というプロパティを実装しなければならない。

 実装を進めていこう。このクラスの実装はそれほど大変ではない。

Provider プロパティのために IQueryProvider インタフェイスを持つクラスを用意する必要があるが、ここでは、それを仮に TwitterQueryProvider クラスとしておこう。 TwitterQueryProvider クラスは後述する。

// QueryableTweets.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

// IOrderedQueryable<string> な QueryableTweets
public class QueryableTweets<TElement> : IOrderedQueryable<TElement>
{
    public Type ElementType
    {
        get { return typeof(TElement); }
    }

    public Expression     Expression { get; set; }
    public IQueryProvider Provider   { get; set; }

    public QueryableTweets()
    {
        Provider = new TwitterQueryProvider(); // IQueryProvider インタフェイスを実装したクラス。後述。
        Expression = Expression.Constant(this);
    }

    public IEnumerator<TElement> GetEnumerator()
    { return ((IEnumerable<TElement>)Provider.Execute(Expression)).GetEnumerator(); }

    IEnumerator IEnumerable.GetEnumerator()
    { return GetEnumerator(); }
}

IQueryProvider なもの (LINQ プロバイダー) を作ろうとしてみよう

続いて、上記 QueryableTweets で使うための、IQueryProvider なものの実装だ。

これは、LINQ プロバイダーと呼ばれるもので、式木としてのクエリーを解釈する。

こちらの実装は大変だ。

クラス名を TwitterQueryProvider として、IQueryProvider を実装していこう。

// TwitterQueryProvider.cs

using System.Linq;

// LINQ プロバイダーの実験用
// まだ IQueryProvider インタフェイスを実装してないのでコンパイル エラー
public class TwitterQueryProvider : IQueryProvider
{}

ここから、Visual Studio でインタフェイスの実装を行うと次のようになる。

// TwitterQueryProvider.cs

using System;
using System.Linq;
using System.Linq.Expressions;

// LINQ プロバイダーの実験用
// Visual Studio でインタフェイスを実装した直後
public class TwitterQueryProvider : IQueryProvider
{
    public IQueryable CreateQuery(Expression expression)
    { throw new NotImplementedException(); }

    public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
    { throw new NotImplementedException(); }

    public object Execute(Expression expression)
    { throw new NotImplementedException(); }

    public TResult Execute<TResult>(Expression expression)
    { throw new NotImplementedException(); }
}

少し実装を進めてみる。

// TwitterQueryProvider.cs

using System;
using System.Linq;
using System.Linq.Expressions;

// LINQ プロバイダーの実験用
public class TwitterQueryProvider : IQueryProvider
{
    IQueryable IQueryProvider.CreateQuery(Expression expression)
    { return null; }

    public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
    { return new QueryableTweets<TElement> { Provider = this, Expression = expression }; }

    public TResult Execute<TResult>(Expression expression)
    { return default(TResult); }

    public object Execute(Expression expression)
    {
        // ここで式木を解釈して、コレクションを作って返す
        return null; // とりあえずは仮に null を返すだけにしておく
    }
}

この中で、ポイントとなるのは Execute メソッドだ。

この Execute メソッドには、式木が渡ってくる。この式木を解釈してやって、そこからコレクションとしての結果を返してやれば良い。

ここは後で実装することにして、とりあえずは null を返すだけにしておく。

ExpressionVisitor の派生クラスで Visitor パターンによる式木の解釈

LINQ プロバイダーの Execute メソッドでの式木を解釈だが、それには、ExpressionVisitor というクラスが使える。

ExpressionVisitor から派生することで、Visitor パターンによる解析が可能となる。

参考: ExpressionVisitor クラス - MSDN

LINQ のための式木をきちんと解釈するのは、かなり大変なことだ。

ここでは、ごく一部の構文にだけ注目して、そこのみに対応することにする。

取り敢えずの最低限のサンプル コード、Where(text => text.Contains("C#")) の形にのみ対応してみる。

尚、この中では、Twitter のタイムラインを取得する TwitterTimeline クラスを使っているが、 TwitterTimeline クラスは後述する。

// TwitterExpressionVisitor.cs

using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

// Visitor パターンで式木を解析して検索用文字列を取り出し、それを使って Twitter のタイムラインを取得する
public class TwitterExpressionVisitor : ExpressionVisitor
{
    public IEnumerable<string> Statuses { get; private set; }

    // 取り敢えずの最低限のサンプル コード
    // Where(text => text.Contains("C#")) の形にのみ対応してみる
    protected override Expression VisitMethodCall(MethodCallExpression expression)
    {
        // もし Where メソッドを呼ぶ式だったら
        if (expression.Method.Name == "Where") {
            // Where メソッドの第二引数であるラムダ式を取り出す
            var lambdaExpression = (LambdaExpression)((UnaryExpression)(expression.Arguments[1])).Operand;
            // そのラムダ式の Body 部を取り出す
            var bodyExpression = lambdaExpression.Body as MethodCallExpression;
            // もし Contains メソッドを呼ぶ式で
            if (bodyExpression != null && bodyExpression.Method.Name == "Contains") {
                // その引数が定数式だったら
                var constantExpression = bodyExpression.Arguments[0] as ConstantExpression;
                if (constantExpression != null) {
                    // その定数の値を検索文字列とし
                    var searchText = constantExpression.Value as string;
                    if (searchText != null)
                        // TwitterTimeline クラス (後述) を使って、タイムラインからその検索文字列にあたる Status を取得しておく
                        Statuses = new TwitterTimeline().Filter(searchText).Select(status => status.Text);
                }
            }
        }
        return base.VisitMethodCall(expression);
    }
}

TwitterTimeline クラスによる Twitter タイムラインの取得

次に、Twitter のタイムラインを取得するためのダミー クラス TwitterTimeline を用意する。

実際に Twitter のタイムラインを取得するコードを用意すれば良いわけだが、今回は説明の簡略化のために CoreTweet というライブラリとダミー コードを用いることにする。

CoreTweet は、Visual Studio から NuGet でインストールできる。

NuGet で CoreTweet のインストール
NuGet で CoreTweet のインストール

ダミー コードは次の通り。

// TwitterTimeline.cs

using CoreTweet; // Twitter のタイムライン取得用
using System.Collections;
using System.Collections.Generic;
using System.Linq;

// Twitter のタイムライン取得用
// CoreTweet ( https://github.com/CoreTweet/CoreTweet/wiki/Home(%E6%97%A5%E6%9C%AC%E8%AA%9E) ) を利用
// NuGet でインストールできる
// Twitterの開発者向けサイト "Twitter Developers" ( https://dev.twitter.com ) にアプリケーションの登録をし、
// Consumer Key、Consumer Secret、Access Token、Access Secret を取得するなどすれば、
// 実際に Twitter のタイムラインから取得することも可能
class TwitterTimeline : IEnumerable<Status>
{
    public IEnumerable<Status> Filter(string searchText)
    {
        // ダミー実装
        // 実際には、ここで searchText にマッチする Status のみを取ってくるのが良い
        return this.Where(status => status.Text.Contains(searchText));
    }

    public IEnumerator<Status> GetEnumerator()
    {
        // "Twitter Developers" に登録し、キーやトークンを取得すれば、実際に Twitter のタイムラインを取れる
        //var tokens = CoreTweet.Tokens.Create("[Your Consumer Key]", "[Your Consumer Secret]",
        //                                     "[Your Access Token]", "[Your Access Secret]");
        //return tokens.Statuses.HomeTimeline().GetEnumerator();

        // ダミー実装
        // 実際には Twitter のタイムラインを取ってくる
        yield return new Status { Text = "C# で CoreTweet を使って Twitter のタイムラインを取得してみた" };
        yield return new Status { Text = "式木いじりは茨の道" };
        yield return new Status { Text = "C#LINQ を使う" };
        yield return new Status { Text = "Hokuriku,NET C# 式木" };
    }

    IEnumerator IEnumerable.GetEnumerator()
    { return GetEnumerator(); }
}

LINQ プロバイダー TwitterQueryProvider への組み込み

では、TwitterQueryProvider に TwitterExpressionVisitor を組み込んでみよう。

Execute メソッドの中で、TwitterExpressionVisitor の Visit を呼ぶ。 すると、TwitterExpressionVisitor が式木を解釈し、結果を Statuses に入れるので、それを返せば OK だ。

// TwitterQueryProvider.cs

using System;
using System.Linq;
using System.Linq.Expressions;

// LINQ プロバイダーの実験用
public class TwitterQueryProvider : IQueryProvider
{
    IQueryable IQueryProvider.CreateQuery(Expression expression)
    { return null; }

    public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
    { return new QueryableTweets<TElement> { Provider = this, Expression = expression }; }

    public TResult Execute<TResult>(Expression expression)
    { return default(TResult); }

    public object Execute(Expression expression)
    {
        // ここで式木を解釈して、コレクションを作って返す
        var expressionVisitor = new TwitterExpressionVisitor();
        expressionVisitor.Visit(expression);
        var statuses = expressionVisitor.Statuses;
        return statuses.AsQueryable<string>();
    }
}

テスト

使ってみよう。

コンソール アプリケーションの Main から使用してみる。

// Program.cs

using System;
using System.Linq;

class Program
{
    static void Main()
    {
        IQueryable<string> query1 = new QueryableTweets<string>();
        IQueryable<string> query2 = query1.Where(text => text.Contains("C#"));

        // ここまでは、式木をつくっているだけ
        Console.WriteLine(query2.Expression);
        Console.WriteLine();

        // 下の foreach 中で実際に値を item に取り出そうとすると、
        // 1. TwitterQueryProvider の Execute にその式木が渡され、
        // 2. TwitterExpressionVisitor でそれが解析される中で、
        // 3. TwitterTimeline がタイムラインの取得を行う

        foreach (var item in query2)
            Console.WriteLine(item);
    }
}

実行結果は、次の通りだ。

value(QueryableTweets`1[System.String]).Where(text => text.Contains("C#"))

C# で CoreTweet を使って Twitter のタイムラインを取得してみた
C#LINQ を使う
Hokuriku,NET C# 式木

始めに式木が表示され、その後で、クエリーの結果 "C#" が含まれる Status が三行表示された。

このサンプルコードの範囲ではうまく動いたようだ。

■ 今回のまとめ

今回は、Hokuriku.NET C# 勉強会『C# 式木』 で説明した内容を補足した。

IQueryable なものを書き LINQ に対応させるのはかなり大変だが、その意味するところだけでも理解していけば、LINQ について理解を深めることができるように思う。

MVP ComCamp -2nd Round- 開催中

MVP ComCamp -2nd Round- Nov 17 - Nov 21, 2014 が開催されている。

初日に開発者向けセッションを担当 (トラック 2 - Day 1 (2014/11/17): Learn フェイズ)。

発表した資料を公開。

関連記事

Hokuriku.NET C# 勉強会『C# 式木』(2014-10-26、金沢) のスライド公開

C#

Hokuriku.NET C# 勉強会『C# 式木』(2014-10-26、金沢) で発表した資料に大幅に加筆して公開。