Xamarin.Froms でパズルゲームを作る(Windows Phone版)

昨日の続きで…と言いますか、実装は昨日のうちに済ませました。移植自体は簡単で1時間かかりません。

image

ちょっと、XAMLを書き直して、コマの大きさを変えたりセンタリングしたりしています。

■ファイルアクセスは ApplicationData.Current.LocalFolder を使う

基本的なところは、iOS/Android と同じなのですが、ファイルアクセス部分がちょっとだけ違います。iOS/Android の場合は、System.Environment.GetFolderPath を使って普通のフォルダアクセス(といえ、アプリ内のフォルダだけなのですが…システムフォルダへのアクセスは要調査)と同様に使えますが、Windows Phone の場合は、ApplicationData.Current.LocalFolder を使います。これは WinRT と同じで、アプリからアクセスできるフォルダが OS 上で制限されているためですね。

このサンプルが「共有プロジェクト」を使っているのは、このためでもあって、以下のように #if でコンパイル時に分岐させます。PCL でやると、ここのコードビハイドが委譲を使ったりして面倒なので、そのままコード共有で。

var se = new XmlSerializer(typeof(MyData));
try
{
#if __IOS__ || __ANDROID__ 
    var documents =
        System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
    var file = System.IO.Path.Combine(documents, "mydata.xml");
    using (var stream = System.IO.File.OpenRead(file))
    {
        var m = se.Deserialize(stream) as MyData;
        m.CopyTo(_model);
    }
#else
    using (var stream = await Windows.Storage.ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(
        "mydata.xml"))
    {
        var m = se.Deserialize(stream) as MyData;
        m.CopyTo(_model);
    }
#endif
}
catch
{
    // 各スコアを0にする
    this._logic.Reset();
}

stream を取るところは一緒なので、Windows Phone で使っている OpenStreamForReadAsync メソッドを、適当に包んでやれば共有化できるのですが…まあ、このままで。気になるのは、iOS/Android で使っているのは OpenWrite で同期メソッドなんだけど、Windows Phone の OpenStreamForReadAsync は非同期メソッドってところですよね。ここは非同期に揃えたいところです。

■ゲームロジックやAzure Mobile Serivces は、PCL で

image

PCL(移植可能)を使っているのはゲームロジックとAzure Mobile Service のところです。カメラ機能とかは Xamarin.Mobile を使えば共有化できるので、シンプルなものならば結構すんなり共有化できるかなと。ただし、カメラを撮った後の遷移が各プラットフォームで若干異なるので、そのあたりはひと工夫が必要そうです。

■画像リソースはどうする?

このアプリでは、画像ファイルを

_mk[0] = ImageSource.FromFile("MarkNone.png")

な感じでファイル名を指定して直接取ってきています。ここのルートが何処を指すかというと、プラットフォーム毎に違っていて、

iOS /Resources/MarkNone.png
Android /Resources/Drawable/MarkNone.png
WinPhone /MarkNone.png

ってな感じで、Windows Phone はプロジェクト直下を示しているという…画像ファイルがちりばめられるのは嫌なので、このあたり WinPhone のために Images フォルダを作成して、

iOS /Resources/Images/MarkNone.png
Android /Resources/Drawable/Images/MarkNone.png
WinPhone /Images/MarkNone.png

とかにしたいところですね。ちなみに、Windows Phone には Resources というフォルダがあるのですが、そこは参照していません。

ただし、画像がたくさんあったり多言語化を考えると、リソースを使いたいわけで、そのあたりは Xamarin.iOS/Android で、文字列と画像をPCLを使って共有させる方法 を使って PCL にしたいところです。ここでの方法は iOS/Android しか対応していないので、WinPhone と WinRT にも拡張したいところですね。

■サンプルコード

もう少し手を入れますが、現状のは Github に
https://github.com/moonmile/TMPuzzleXForms

カテゴリー: Android, Xamarin, iOS | Xamarin.Froms でパズルゲームを作る(Windows Phone版) はコメントを受け付けていません

Xamarin.Froms でパズルゲームを作る(iOS/Android版)

de:code の直前に発表になった Xamarin.Forms ですが、拙著のサンプルも、それぞれビューを作っているわけで。

日経BP書店|C#によるiOS、Android、Windowsアプリケーション開発入門
http://ec.nikkeibp.co.jp/item/books/P98340.html

そんな訳で、サンプルコードの TMPuzzle を Xamarin,Forms にコンバートしています。サンプル自体は一枚絵(ひとつのビュー)になっているので、比較的コンバートは楽なハズ…なのですが、いくつかコツが要りそうなでメモ的に残しておきます。

まだ途中の段階ですが、iOS/Android版を Github に公開しておきます。
https://github.com/moonmile/TMPuzzleXForms

■ビューを XAML で作る

https://github.com/moonmile/TMPuzzleXForms/blob/master/TMPuzzleXForms/TMPuzzleXForms/MainPage.xaml

サンプルでは、axml/storyboard/XAML で作ったので、今回も XAML で作ります。Xamarin Studio ではデザイナは動かないのですがコード補完ができるのでだいたいの動きが想像できます。デモのサンプル https://github.com/xamarin/xamarin-forms-samples にある ButtonXaml が XAML を使ったコードです。*.xaml と *.xaml.cs の2つがあるので、コードビハイドが書けます。MVVM スタイルにするときはバインドを使えばいいのですが、ここではがりがりとコードを書きつけてしまいます。バインド自体は、MS謹製のXAMLと同じように Text=”{Binding …}” の構文で書けるので、ここは便利。使えるコントロールは http://iosapi.xamarin.com/?link=N%3aXamarin.Forms を参照すれば OK です。TextBox が Editor になっているとか、いくつか違いがありますが、このあたりは iOS/Android/Windows の混合になるので仕方がないところです。

ビュー自体は、レイアウトが異なるので、http://developer.xamarin.com/guides/cross-platform/xamarin-forms/controls/layouts/ を見てベースを決めます。TMPuzzle は Windows ストア寄りに作ってあるので Grid を使ってみたのですが、iOS だとうまくレイアウトができませんね。スマートフォンのような小さ目の画面であれば? Frame を使って iOS のように位置固定(Windows の Xaml ならば canvas)で良いかもしれません。TMPuzzle 自体はゲームアプリなので、たくさんのコントロールを乗せていますが、普通のコンテンツを表示するならば、ContentViewStackLayout でもいいかもしれません。

image

プロジェクトの構成は、Blank App (Xamarin.Forms. Shared) を使っています。PCL でも良いのですが、サンプル自体はコードビハイドを使っているのと、プラットフォームごとの処理が必要になって時には共有プロジェクト内で #if してしまえばよいので、こっちのほうが融通が利きます。

image

https://github.com/moonmile/TMPuzzleXForms/blob/master/TMPuzzleXForms/TMPuzzleXForms/App.cs 共有プロジェクトの App.cs を書き換えます。MainPage.xaml を共有プロジェクトに追加したので、new MainPage() でページを作成します。コードビハイドの場合は、このあとゴリゴリ内容を書いていますが、ひとまず XAML を書いて Andorid か iOS のシミュレーターで動かすとよいでしょう。

public class App
{
	public static Page GetMainPage()
	{
		return new MainPage();
	}
}

画像リソースも多分、共有プロジェクトにおけるハズなのですが、フォルダが異なる(Android の場合は Resources/Drawable、iOS の場合は Resources)となるので、各プラットフォームのフォルダに置いています。画像リソースは一律、

var img = ImageSource.FromFile("MarkNone.png");

のように取り出せるので、iOS/Android を区別する必要はありません。

ちなみに、Xamarin.Forms とは関係ないですが、ファイル呼び出しは

var file = System.IO.Path.Combine(documents, "mydata.xml");

のように共通化できます(Windows Phone の場合は調査中)。

■MainPage.xaml.cs

https://github.com/moonmile/TMPuzzleXForms/blob/master/TMPuzzleXForms/TMPuzzleXForms/MainPage.xaml.cs

ページを表示するときの初期化は、Android では OnCreate、iOS では ViewDidLoad になるのですが、Xamarin.Forms では(多分)OnAppearing です。 ヘルプを見ると When overridden, allows application developers to customize behavior immediately prior to the Xamarin.Forms.Page becoming visible. とあるので、次回表示するときも呼び出されてしまうような気がするのですが、ここは要調査ですね。TMPuzzle は1枚絵なのでこれを使っています。

各プラットフォームで呼び出す MainActiveity や AppDelegate はそのままです。もともと共通化を意識して作ったサンプルプログラムなので、Xamarin.Forms に移植するとプラットフォーム毎の差がほとんどなくなって、画像ファイルの切り替えぐらいになります。

■画像のクリックイベントはTapGestureRecognizerを使う

Button コントロールには Click イベントがあるのですが、ImageやLabelなどには Click イベントがありません…というか、タップイベント全般がありません。ざっと調べてみると、コントロールに対するユーザーイベントは Click と TextChanged ぐらいしかありません。
うーむ、困った。これで万事休すかな、と思ったのですが TapGestureRecognizer ってのがありました。iOS と同じでコントロールに対するイベントを取ってきます。

TapGestureRecognizer tapGestureRecognizer = new TapGestureRecognizer
{
    TappedCallback = img_Click
};
// 表示用マークにイベントをつける
_marks = new Image[DataModel.BOARD_X_MAX * DataModel.BOARD_Y_MAX];
_tags = new Dictionary<Element, int>();
for (int i = 0; i < DataModel.BOARD_X_MAX * DataModel.BOARD_Y_MAX; i++)
{
    var img = _marks[i] = this.FindByName<Image>(string.Format(&quot;mark{0}&quot;, i));
    img.GestureRecognizers.Add(tapGestureRecognizer);
    _tags[img] = i;
}

こんな風に、イベント先の img_Click を設定しておいて、img.GestureRecognizers.Add のように追加していきます。GestureRecognizers 自体は、View クラスにあるので大抵のコントロールにはついています。

いわゆる sender が View オブジェクトで渡されるので、これを目的のコントロールにキャストします。引数自体は object 型なのですが、中身は不明。Image をクリックすると null が来ています…が、ひとまず画像やラベルのタップイベントを取得できます。

public async void img_Click(View view, object args)
{
    // 再入禁止
    if (_flag == true) return;
    _flag = true;
    Image mark = view as Image;

■Android と iPhone の動作

同じ XAML ファイルを使ったのですが、iOS のほうがレイアウトが崩れています。というか、Grid だとちょっと辛いものがありそうですね。Xamarin.Forms のサンプルは、flowlayout を使っているので、どれも同じようになりますが、複雑なレイアウトの場合にはそれぞれの調節が必要っぽいです。

image

image

引き続き Windows Phone を作成。

カテゴリー: Android, Xamarin, iOS | Xamarin.Froms でパズルゲームを作る(iOS/Android版) はコメントを受け付けていません

Dynabook Tab VT484 で Kindle を動かす

Windows タブレット dynabook Tab VT484 トップページ
http://dynabook.com/pc/catalog/d_tab/131118vt484/index_j.htm

de:code の「教材」として配布されたタブレットですが、何に使うのか…とおもったけど、ひとまず Kindle を入れます。以前やった Windows 8 Pro に Bluestacks を入れれう方法と同じです。

日本語Windows 8 Pro で Kindle を動かす方法 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/4606

タブレットなので

  • Kindle と同じように使える?
  • Suface RT だとエミュレータが入らないけど、Dynabook Tab の場合は Windows 8.1 だから大丈夫。

ってことです。エミュレーター上で動くので若干動きが遅い(特にストレージアクセス時が遅い?)のですが、一度立ち上げてしまえば普通に読める状態になります。WiFi 経由が遅いのか、エミュレーターが遅いのか分からないのですが、漫画を読み込んだときにかなり待たされますが、これも一度読み込めば普通にページがめくれます。

こんな感じに横置きにすると2ページレイアウトで。

image

縦置きにすると1枚のレイアウトになります。

20140608_02

Bluestacks のほうは、bluestacks.com から、ダウンロードすれば OK。

■解像度を変更する

普通に Bluestacks を Danyabook tab に入れただけだと、こんな風にタブレットを縦にしても、画面が横になります。逆にタブレットを横にすると bluestacks の画面が横になります。

image

おそらく、タブレットの向きと bluestacks の向きの認識が逆転してるんですよね。幸いにして、Bluestacks は解像度を変えられるので、縦横を逆転させて設定します。

我的PC古箱 dynabook Tab VT484 購入レビュー / カスタマイズ/ VT484/26K PS48426KNLG
http://sc440ge.blog59.fc2.com/blog-entry-177.html

解像度はレジストリにあります。

[HKEY_LOCAL_MACHINESOFTWAREBlueStacksGuestsAndroidFrameBuffer]
“Width”=dword:0000042a
“Height”=dword:00000258
“Depth”=dword:00000010
“FullScreen”=dword:00000000
“WindowState”=dword:00000001
“HideBootProgress”=dword:00000001
“EmulatePortraitMode”=dword:00000001

元の解像度が 1066 x 600 の変則パターンなので、

[HKEY_LOCAL_MACHINESOFTWAREBlueStacksGuestsAndroidFrameBuffer]
“Width”=dword:000002F8
“Height”=dword:000004D8
“Depth”=dword:00000010
“FullScreen”=dword:00000000
“WindowState”=dword:00000001
“HideBootProgress”=dword:00000001
“EmulatePortraitMode”=dword:00000001

これを 760 x 1240 にします。これは、dynabook tab の 800 x 1280 から 40 ずつ引いた値です。800 x 1280 に設定すると何故か縦置きのときに Kindle がうまく表示できないんですよね。そこで縦横からタスクバーの幅(40ドット)だけ引いています。

これを bluestacks-760×1240.reg のようにファイルに保存して、ダブルクリックすればレジストリに書き込まれます。

ちなみに、dynabook tab はミニ usb なので、普通の USB キーボードがつなげられません(コンバーターを使うか、bluetooth を使うか)。キーボード打ちはちょっと面倒なので、こんな風に「リモートアシスタンス」を使います。dynabook tab のほうで「msra」で動作させれば OK です。

image

本来ならば、手っ取り早く Windows 8.1 Pro にアップデートするのがいいのでしょうが、再インストールが必要なので躊躇しております。Update 版を1万ちょっとで買えばいいんだけど、それだけのために買うのもなぁ、という感じです。まあ、ファイル共有は普通の Windows と同じようにできるので、ファイルの受け渡しは楽ですね。Surface の場合は、別途レジストリを弄るか、ホームグループを使う必要がありますから。

普段使いは白黒 Kindle を使っているので、カラー版を見たいときに使うかなぁ、といったところ。あとは、ストアアプリ版だと面倒なので、WPF で自作ツールを入れるとか。主に動画ビューアとしてですが…いや違うか、「教材」なのだから、ぜひとも Lumia と一緒にユニバーサルアプリを作らないといけないわけですが。まだ Lumia は 8.1 にアップデートしておりませぬ。

カテゴリー: 雑談 | Dynabook Tab VT484 で Kindle を動かす はコメントを受け付けていません

F# の Async と C# の async/await を相互運用する方法…を模索中

de:codeも終わったので、勢いで Xamarin Tシャツアプリを F# に書き直してます。Xamarin Tシャツアプリってのは、http://xamarin.com/studio から Xamarin Studio をダウンロードして、ダウンロードしたソースコードをビルドすると Tシャツを注文するアプリが作れます。それを実際に送信すると、Xamarin 社が C# の Tシャツを送ってくれるという販促アプリです。
で、じゃあ、F# で書いたらどうなるのか?ってのと、F# で送ったら F# Tシャツを送ってくれるかどうか…は別として(多分無理でしょう)、F# のアプリが iOS/Android で動くよ、の実践版のつもりです。実際 C# のコードをダウンロードすると、Web Service に接続しているし、リストボックスとか POCO のデータアクセスなどを使っている、iOS のグラフィック機能を使ってごちゃごちゃやっているという結構な代物でした。その中で、サーバーアクセスなどで頻繁に await/async をやっています。

ざっと F# に書き直しながら思ったのは、

  • 非同期処理の async/await が頻繁に出てくる
  • データバインド絡みの Obeserver パターンが出てくる

この2点を F# でも書けないといけない。非同期処理自体は Windows ストアアプリでも頻繁に出て来るのですが、WinRT へ F# からアクセスできない(?)ので、まだ問題になっていない模様。しかし、Xamarin.iOS/Android を使って F# をアプリを作るときは、C# の async/await は避けられないわけで、このあたりはうまく C# と F# で相互運用したいところです。

Async in C# and F#: Asynchronous gotchas in C# (Japanese translation)
https://gist.github.com/pocketberserker/5565303
Async in C# and F#: Asynchronous gotchas in C#
http://tomasp.net/blog/csharp-async-gotchas.aspx/

これは、話題になった時にざっと読んで、F# と C# で Async の扱いが違うのか、漠然と思っていたわけですが、いやいやいや、Async が違うというんじゃなくて、そもそもこの話題で出てくる F# の Async はコンピュテーション式の AsyncBuilder で、C# の async/await は Awaitable パターンの実装だから、そもそもが違うがな(と自分が勘違い)していたことが、今日わかりました。なるほど。そうなると async/await を Async{} で単純に置き換えることができないわけで、更に言えば、.NET Framework の *Async メソッドの扱いと、F# の Async{} の扱いを両方やらないと駄目ってことですね。Task<‘T> と Async<‘A> ってことです。

■Async は Async<‘T> を返す

let workThenWait() =
  async {
      Thread.Sleep(1000)
      printfn &quot;work done&quot;
      do! Async.Sleep(1000)
  }

let demo() =
  let work = workThenWait() |> Async.StartAsTask
  printfn &quot;started&quot;
  work.Wait()
  printfn &quot;completed&quot;

workThenWait() が非同期で動いている間、待っているという書き方です。
Async.StartAsTask では、まだ実行されていなくて(タスクだけ作られて)、work.Wait() でタスクが実行されます。work の型は、Async<‘T> で、終了時に戻り値を返せます。

これを、素直に C# に直すと、こんな感じ。

async Task WorkThenWait()
{
    Thread.Sleep(1000);
    Console.WriteLine("work");
    await Task.Delay(1000);
}

async void Demo()
{
    Console.WriteLine("started");
    await WorkThenWait();
    Console.WriteLine("completed");
}

WorkThenWait() の位置が、started の後ろにずれて、await で非同期待ちをします。正確には非同期実行&待ちをするわけで、元ネタでいう、var child = WorkThenWait(); と child.Wait(); にあたります。
これから勝手に推測して、Async{} ってのを async/await に直せばよいか?って思うわけですが違っていて、C# の async/await のほうは Task<‘T> を返します。

■async/await は Task<‘T> を返す

下記の例では Task を返すように書き方もの。
C# では、async で修飾すれば、Task を返すのにラムダ式を使わなくてよいし、非同期待ちをするのに、Start(), Wait() を羅列しなくてもよい。更に戻り値を受けるときも、t.Result を使う必要もなく await が使える。

let workThenWait2() =
    new Task( fun _ ->
              Thread.Sleep(1000)
              printfn &quot;work done&quot;
              Thread.Sleep(1000)
            )

let demo2() =
    let t = workThenWait2()
    printfn &quot;started&quot;
    t.Start()
    t.Wait()
    printfn &quot;completed&quot;

int 型の戻り値を返したときは、こんな風に書く。

let workThenWait3() =
    new Task( fun _ ->
              Thread.Sleep(1000)
              printfn &quot;work done&quot;
              Thread.Sleep(1000)
              1 // 戻り値
            )

let demo3() =
    let t = workThenWait3()
    printfn &quot;started&quot;
    t.Start()
    t.Wait()
    let res = t.Result
    printfn &quot;completed&quot;

■何が問題か?

F# だけでやっているときは、Async{} を使えばいいのだけど、C# と相互運用したいときとか、非同期の .NET Framework クラスを使いたいとき(WebClientとか)に結構困る。Async と async/await が混在するのもそうだけど、Async<‘T> なのか、Task<‘T> なのかを区別しないといけない。

  • WebClient で使う Async 系のメソッドは、Task<‘T> を返すので、これに合わせる。
  • C# で作った Async 系のメソッドは、Task<‘T> を返す。
  • C# へ渡す非同期タスクは Task で渡す必要がある。
  • F# 内で閉じているときは Async{} を使う

というパターンが必要になる。

■F# 用の await を自作する

まず Task<‘T> を受けるための await を自作します。

type Async() =
    // await を自作する
    static member await (t:Task) =
        t.Start()
        t.Wait()
    static member await (t:Task<'a>) =
        t.Start()
        t.Wait()
        t.Result

一度、Await で包んであるのは、await メソッドを多重化するため。戻り値無しだけ作るという方法もありでしょう。
使い方は、C# の await とは違って、後ろにつけます。Async.StartAsTask と同じ方法ですね。

let demo2a() =
    printfn &quot;started&quot;
    workThenWait2() |> Async.await
    printfn &quot;completed&quot;

let demo3a() =
    printfn &quot;started&quot;
    let res = workThenWait3() |> Async.await
    printfn &quot;completed&quot;

同じように、Async<‘T> を引数に取る await メソッドも作っておきます。

type Async() =
    // await を自作する
    static member await (t:Task) =
        t.Start()
        t.Wait()
    static member await (t:Task<'a>) =
        t.Start()
        t.Wait()
        t.Result
    static member await (t:Async<'a>) =
        ( t |> Async.StartAsTask ).Wait()

こうすると、どちらの場合も Async.await で処理して統一できるので便利。

let demo1a() =
  printfn &quot;started&quot;
  workThenWait() |> Async.await
  printfn &quot;completed&quot;

■Task を作る TaskBuilder を作ればよい

C# の Task<‘T> は楽に処理できるようになったので、今度は F# で Task<‘T> を作って C# に渡す、というパターンを考える。async の task 版といったところ。

let workThenWait3() =
    new Task( fun _ ->
              Thread.Sleep(1000)
              printfn &quot;work done&quot;
              Thread.Sleep(1000)
              1 // 戻り値
            )

このようなラムダ式の書き方を、以下なようなコンピュテーション式に直せればOK。これは AsyncBuilder のソースを見て直せばいいかな?

let workThenWait3() = task {
              Thread.Sleep(1000)
              printfn "work done"
              Thread.Sleep(1000)
              1 // 戻り値
            }

こっちは後日。

~~~
こちらも参照

AsyncBuilder extension for maniplating other containers by using keyword | F# Snippets
http://www.fssnip.net/jj

カテゴリー: 開発, F# | 3件のコメント

de:code 2014 の感想戦

de:code | 日本マイクロソフトの開発者/アーキテクト向けイベント – Microsoft Events & Seminars
http://www.microsoft.com/ja-jp/events/developer/

結論から言えば、何かと前評判が悪かった de:code ですが、蓋を開けてみれば「損はさせません」のツイートは本当でした。値段相応なのか、値段以上なのかはさておき、自分の言ったセッションをメモ書きしておきます。

キーノートはプレゼントの発表が二転三転したのでさておき、

DE-023 Windows アプリ開発、どこへ向かうのか

お昼に「.NET開発テクノロジ入門 2014年版」を買って読みながら奥主さんの話を聞く。行く予定のプレゼン資料は事前に OneNote で配布されていたので、そのまま Surface に入れてひと通り見ておく。紙の資料がないので、手荷物が少なくてよい。メモしたいときは OneNote に書くか、自分のメモ帳に書くか。今回は Twitter にちらちらと流すだけで十分かと思ってメモは取らず。全体というか、de:code の歩き方になるので、デバイス関係の事前内容がわかる。

DE-018 Windows ストア アプリ開発、テスト、デバッグ、ストアへの提出

4人のエバンジェリストがリレー式にストアアプリの最初から最後までってことで、ひと通り流し。初心者向けになっているけど、この道は何度も通るし、少しずつ情報が変わる(便利になるという意味で)。WinJS は少し手を付けてみたい。

TL-003 最新 Web API 開発 ~ASP.NET API 2 とクラウドの活用~

ASP.NET MVC と Web API 絡みの情報集めとして。WCF の複雑さから、REST、OData にして疎通を簡単にする感じに向っている。クロスプラットフォーム(特にマルチクライアント)ならば当然の帰着という感じで。OData はなんとなくわかったので、後で認証まわりと合わせて、ASP.NET MVC と合わせて知識埋め。

DE-015 Visual Studio 2013 Update 2 と HTML5 によるクロスデバイス、クロスプラットフォーム開発の全貌

HTML5/WinJS を使って、ストアプリ、Windows Phone、ブラウザアプリを共通に作れるという話。ブラウザを含められるのは Javascript ならではで、これは、Xamrin.iOS/Android の WebView にも含められるかも。CORDOVA/PhoneGap を使えば、ブラウザ的な UI を持ってくるのは楽になる。逆にストアアプリ風の UI をブラウザに表示させることも可能。

DE-010 デスクトップ アプリケーションと Windows ストア アプリの連携

同じ PC にあるのに、デスクトップアプリとストアアプリの連携は非常に制限されている。のだが、Windows 8.1 Update からサイドローディングに限り、ローカル PC へのループバックを許可、さらにアプリブローカーを通してデスクトップの COM へアクセスできる。これができるということは、大抵の業務ロジックを COM にして動作させることが可能…なんだが、現実は View にべったりだったりして無理なんだろうな。デスクトップ DLL を有効に使いたいときに利用するテクニック。

SV-014 ハードウェア構築・管理のない世界 ~ Azure 仮想マシンの現実 ~

Azure プログラミングはいくつかやったけど、なぜか仮想マシンは作ったことがない。Linux を動かしたいならレンタルサーバを借りたほうが安いから、とも思っていたのだが、スナップショットを取れるとか、ローカルで作成した HD をアップロードできるから環境構築はこっちのほうが効率的かもしれん。試験用に CentOS+CakePHP で作ってみるかも。

DE-005 VWindows Phone 8.1 プラットフォーム徹底解説

Windows Phone は完全にノータッチだったのだが、ユニバーサルアプリがあるので、ストアアプリ(タブレットアプリ)からのアプローチのひとつとして聞きに行く。WP8 から Windows NT カーネルに変わったということで、WinRT と共有化できる準備ができる。Xamarin.iOS/Android に Xamarin.Forms が加わったので、UI 的にも Windows Store/Phone を加える環境が整ってきている。先の WinJS/HTML5/WebView と組み合わせる自由度が高い。ちなみに、私の教材は Lumia 1520 なので解像度がフルHD。電話にしてはでかいので、私としてはタブレットとして使う。Sim を持ってないし。

SN-005 C# を使い倒す iOS/Android 開発の新潮流

人のうわさを聞くためと、どんな人が興味があるのか?な感じでお昼。「C#によるiOS、Android、Windowsアプリケーション開発入門」に興味を持ってもらえるかってこと。環境としては、Visual Studio で作れるのだが、有償というのはそれなりに敷居が高い。カンファレンス内では使用期間3か月のチケットを配るそうなので、まずは使って貰えるパターンかと。ただし、Xamarin の本格的なターゲットは iOS/Android アプリ作成にあるので(今後は Windows Phone も加わるが)、通常のデスクトップアプリ作成経験だけだと難しいかも。Windows ストアアプリ作成との並行して行うのがおすすめ。あと、まだ Phone のほうに目が向いていることが多いが、実は Tablet のほうに勝機がある。

DE-017 Windows ストア アプリ で収益を上げるには

手元にもある「アプリ内課金+広告 iPhoneプログラミング」の Windows 版。いまのところ、アプリの有償手段は、「ユーザーに直接売る」「内部課金する」「広告を出す」の3種類しかない。無料の場合は「広告アプリとして出す」(最近の映画関連のゲームアプリとかがそれ)、「実力/テンプレートを示す」(他の案件とつなげる)というパターンがある。会社/個人の違いやターゲット(ゲーム/書籍/非ゲーム)もあるし、何を売るか?(コンテンツなのか技術なのか)ってのもある。Xamarinを含めると、iOS/Android/Windows Store/Windows Phone と 4種類になるので、これのそれぞれで、ダウンロード販売/アプリ内課金/広告を表示、の共通化を考える時期なのかも。

AR-006 マルチデバイスアプリ開発における設計戦略 ~ Webか? ネイティブか? あるいは両方か?

結論からあれば、いろいろ選択肢が用意されているので、前提条件(既存コンテンツか新規か、簡易アプリか複雑な操作か)によって選択する必要がある。既にブラウザコンテンツがあれば HTML5 をそのまま使えるパターンができるし、さらにちょっとして工夫が加えられる。WebView ならば Invoke を使うとか、逆にネイティブ操作でも詳細やヘルプ表示に WebView を使うとか。カードゲームアプリは WebView を使っているものが多いが、逆にマップはネイティブで作ってカード表示をネイティブらしくHTMLで作るという方法もある。

DE-006 ユニバーサル Windows アプリの画面設計 ~ 4 インチから 82 インチまで ~

実は iPod nano は正方形画面で、いくつかのフォト機器は正方形だったりする…のだが、そうそう、パズルアプリの画面を正方形にしておくと縦と横の両方に対応できる。で、旧スナップの横 500px の縦置きが今後の考えどころ。あと、flush paint のように、横置き全画面以外は動作しない、というのもアリなのかってのは目から鱗だった。確かにアプリがユーザーの使い方を規定してもよい。DPI に関しては考える必要がないし、DPI の高さについてはハード屋さんが熟知しているので、ソフト屋としてはもうちょっとアプリのほうに目を向けて。

DE-007 C#/.NET で iOS/Android アプリを開発 ~ Xamarin で実現するクロスプラットフォーム開発 ~

自分の締めとして Xamarin の話。デモは、おととい発表されたばかりの Xamarin.Forms を含めて。WebView で Razor を使うトリッキーなコードは、なるほどその手があったかという感じ。ループとかバインドを頻発するときには重宝しそうな感じ。いや、後からよく考えたら JQuery とか使ったほうがよいかも w。ただ、このカンファフェンスを通して Windows Phone, Xamarin で感じたのは、ここまで他のプラットフォームを連呼する Microsoft になったのだなということ。キーノートでもあったけど、Windows を連呼していた Windows DNA あたりの時期から一変している。

C#によるiOS、Android、Windowsアプリケーション開発入門 

日経BP書店|C#によるiOS、Android、Windowsアプリケーション開発入門
http://ec.nikkeibp.co.jp/item/books/P98340.html

そんなわけで、教材として貰った/買った dynabook tab と Lumia 1520 どうするかと模索中。現在dynabook のほうは windows 8.1 update までして、サブディスプレイ状態(苦笑)。Lumia のほうは 8.0 のままで…後で、開発者登録しないと。

カテゴリー: 開発 | de:code 2014 の感想戦 はコメントを受け付けていません

後付け言語 post を考えてみる

自前の関数型電卓のパースが間に合わなかったのと、先週の.NETラボ勉強会で「関数型言語の本質とは?」にうまく答えられなかったので、それっぽい言語を考えてみる。

うーん。私自身は関数型言語自体を扱っている期間が短いので、先駆者の言葉を借りれば「関数プログラミング」から「式が簡略化できる」ことと、「型システム入門」から「型が決まる/推論可能である」ことに尽きる…と思うのだけど、じゃあ、オブジェクト指向型言語との違いは?というと、なんだろう。
実は、「オブジェクト指向型言語は内部に状態を持つ、対して関数型言語は内部に状態を持たない」というのは正しいのだけど、オブジェクト指向型言語に根拠があるので、これは「ごまかし」である(ごまかしと分かっていて言うんだけど)。でも、状態を持たない(あるいは持てないように作る)ので、パラレル化がしやすいし、ドメイン駆動設計による分散に対象になる(内部にアトムを持たないので)。

で、懇親会で話したように、

  • 「オブジェクト指向による関数型言語」
  • 「関数型指向によるオブジェクト指向型言語」

ってのも考えられるわけで、どちらの排他的なものにはならない。特に F# の場合は、内部でクラスが作れるしオブジェクト指向的な .NET Framework も使えるわけで、そのあたりは良しなにハイブリット的に作れる。加えていれば、LISP は LISP なので、関数型言語に入れると怒る人がいるかもしれない。

以前、Ruby で後付メソッドが作れる、JavaScript のプロトタイププログラミングを知った頃に、すべてのメソッドのプロパティが virtual であればよかろうというのを思いついたことがある。今でいえば、C# の dynamic なんだけど、F# の型推論と組みあわせると、もっと静的言語に近い形で実現できないか?と妄想してみる。

view =
 name = "masuda tomoaki"
 address = "tokyo"
 age = 46

 button.click = 
  db.submit (name,address,age)

name is TextBox
address is ComboBox
age is TextBoxOnlyNumber
button is Button

.submit t = 
 insert into Person values ( t.name, t.address, t.age )

F# も C# もそうだけど、関数定義やクラス定義は前置参照が基本になる。これはコンパイル時点にワンパスになるような工夫でもあるし、コンパイル時の時間短縮でもある。しかし、Javascript や ruby のように後付けでメソッドが作れる場合は(先付のメソッドとは完全に同じではないにせよ)実行時にメソッドの存在をチェックすることになる。

が、これを型推論をフルに使って「あらゆるオブジェクトのメソッド/プロパティを後付けできる」と定義してしまう。先の例だと view で、やりたいことは「name, address, age の3項目があってデータベースに登録する」」ということなので、それを先に書く。これらがどういうものかは後で書く。

「name is TextBox」ってのは、正確に書くと「name that is TextBox」になる。詳細を that で補完していく英語の構文になる。先に適当なことを書いて、後から追記する方式です。

更に言うと、この .submit 部分はあとから上書きができて

.submit t = 
 insert into Person values ( t.name, t.address, t.age )

.submit t = 
 fs = open "person.txt"
 fs.write t.name t.address t.age

のように後ろに二番目の .submit をつけると、これが採用される。普通は前置メソッドが優先されるが、後付け言語 post では、後から定義したほうを採用するので、後ろの .submit が使える。

当然、null オブジェクトのメソッドはどうなるか?とか問題があるけど、Objective-C の nil のように、無視する。こうなると、obj.?method のような変な記号を使わなくていいので、タイピングが楽になる…ハズ。

もうちょっと適当に考えると、

main
 v1 = (10,20)
 v2 = (30,40)
 ans = v1 + v2
 printfn ans

main.(+) x y = 
 ( x[0] + y[0], x[1] + y[1] )

main.(+) x y = 
 ( x.0 + y.0, x.1 + y.1 )

main.(+) x y = 
 this.left  = x.left + y.left
 this.right = x.right + y.right

.left (x,y) = x
.right (x.y) = y

.left   (x,y,z) = x
.middle (x,y,z) = y
.right  (x,y,z) = z

こんな風にベクトルの計算を考える。型推論を使えば、2つの .right メソッドは容易に区別がつくので、間違わない。むろん、プログラミングしているときは間違えそうな気もするけど。

カテゴリー: 開発 | 後付け言語 post を考えてみる はコメントを受け付けていません

Xamarin.iOS/Android で、文字列と画像をPCLを使って共有させる方法

Xamarin.iOS/Androidアプリで、バンドルリソース処理を完全共通化できそうな仕様 – Qiita
http://qiita.com/kochizufan/items/69d69f37cf991d452226#comment-172bac67ec6257dc81c2
Embedded Resource | Xamarin
http://docs.xamarin.com/content/EmbeddedResources/

多分、PCL を使うと共通できるだろうなぁ、とは思っていたのですが、これといってよい方法が思いつかなかったのです。iOS/Android それぞれのプロジェクトに入れるしかないか(コピーあるいは共有プロジェクト)とは考えていたものの。なるほど、PCL のアセンブリから直接リソースを読みだす技がありましたね。

https://github.com/xamarin/mobile-samples/blob/master/EmbeddedResources/SharedLib/ResourceLoader.cs

のソースをざってと見ていたのですが、iOS/Android 側で GetEmbeddedResourceStream メソッドを呼び出さないといけないのが難点です。と言いますか、PCL の .NET ライブラリには、Assembly クラスの static メソッドが非常に制限されていて、なんともしようがないのです。と思っていたのですが、typeof(ResourceLoader).GetTypeInfo().Assembly という技で、通常の Assembly を取れる技を知りました。
いやいや、よくよくリソースファイル Resources.Designer.cs を覗いてみれば、

global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("XamarinPortableRes.Lib.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly);

なる書き方がされていて、なーんだ。普通に使える方法じゃないですか。

■文字列リソースを追加する

Embedded Resource の例では、文字列リソースをテキストファイルから読み込んでいますが、これは普通のリソースにしたいですよね。普通に「プロジェクト」→「リソース」で文字列を追加できます。

まだ試してはいませんが、国際化による言語切り替えもこれでやると楽かと。

■文字列リソースを使う

使う側も簡単です。string 型で返してくれるので、そのまま Text プロパティなどに設定できます。

Android の場合

FindViewById(Resource.Id.textView1).Text =
    XamarinPortableRes.Lib.Properties.Resources.Message1;

iOS の場合

this.text1.Text = XamarinPortableRes.Lib.Properties.Resources.Message1;

■画像リソースを追加する

PCL プロジェクトのリソース追加は「文字列」のみに制限されています。制限されている理由はわからないのですが、無理やり突っ込んでも *.resx ファイルから *.desinger.cs に変換でダメになるので、そのままでは使い勝手が悪いです。
なので、Resources というフォルダを作って、画像ファイル(pngファイルなど)を入れます。プロパティウィンドウでビルドアクションを「埋め込まれたリソース」にしておきます。こうすると、先の「バンドルリソース処理を完全共通化~」に書いてあるように「XamarinPortableRes.Lib.Resources.MarkBlue.png」のように、ドットつながりでリソースが取れます。

このリソース名をそのまま使ってもいいのですが、文字列指定を間違えると実行エラーになるし、どうせならばインテリセンスが効くようにしたいので、少しだけ工夫します。

こんな風に、リソースを取り出すための ResourceLoader クラスを作ります。ResourceManager みたいなものです。リソース自体は1回しか読み込まないので、static で十分です。名前から検索するのは Embedded Resource の借用ですが、初回のみ GetManifestResourceNames メソッドでリソース名の一覧を取得します。

public static class ResourceLoader
{
    static internal string[] Names { get; set; }
    static internal Assembly Assembly { get; set; }

    public static System.IO.Stream GetObject(string resourceName)
    {
        if (ResourceLoader.Assembly == null)
        {
            ResourceLoader.Assembly = typeof(ResourceLoader).GetTypeInfo().Assembly;
            ResourceLoader.Names = ResourceLoader.Assembly.GetManifestResourceNames();
        }
        try
        {
            string path = ResourceLoader.Names.First(x => x.EndsWith(resourceName, StringComparison.CurrentCultureIgnoreCase));
            return ResourceLoader.Assembly.GetManifestResourceStream(path);
        }
        catch
        {
            return null;
        }
    }
}

インテリセンスが効くように Resources クラスに「手動」でプロパティを作ります。このあたりは T4 で作ってもいいし、まあ色々。これで、Stream までは取得できます。

public class Resources
{
    public static System.IO.Stream MarkBlue
    {
        get { return ResourceLoader.GetObject("MarkBlue.png"); }
    }
    public static System.IO.Stream MarkGreen
    {
        get { return ResourceLoader.GetObject("MarkGreen.png"); }
    }
    public static System.IO.Stream MarkNone
    {
        get { return ResourceLoader.GetObject("MarkNone.png"); }
    }
    public static System.IO.Stream MarkOrange
    {
        get { return ResourceLoader.GetObject("MarkOrange.png"); }
    }
    public static System.IO.Stream MarkPurple
    {
        get { return ResourceLoader.GetObject("MarkPurple.png"); }
    }
    public static System.IO.Stream MarkRed
    {
        get { return ResourceLoader.GetObject("MarkRed.png"); }
    }
}

■画像リソースを使う

画像リソースから取ってくると、System.IO.Stream を取得できますが、そのままだと扱いにくいので System.Drawing.Bitmap にしたいところなのですが、iOS/Android とそれぞれ異なる(UIImage, Android.Graphics.Bitmap)ので、ヘルパーメソッドを作っておきます。

Android の場合は、Stream から Bitmap を返すまで。

global::Android.Graphics.Bitmap ToBitmap(System.IO.Stream st)
{
    using (var mem = new System.IO.MemoryStream())
    {
        st.CopyTo(mem);
        st.Close();
        var data = mem.ToArray();
        var bmp = global::Android.Graphics.BitmapFactory.DecodeByteArray(data, 0, data.Length);
        return bmp;
    }
}

こんな風に画像設定をします。

this.imageBlue = FindViewById(Resource.Id.imageView1);
imageBlue.SetImageBitmap(ToBitmap(XamarinPortableRes.Lib.Resources.MarkBlue));

iOS の場合は、UIImage を作成します。

UIImage ToBitmap(System.IO.Stream st)
{
    var data = NSData.FromStream( st );
    st.Close();
    var bmp = UIImage.LoadFromData(data);
    return bmp;
}

そして、設定

this.imageBlue.Image = ToBitmap(XamarinPortableRes.Lib.Resources.MarkBlue);

本来は ToBitmap まで共通化したいところですが、それぞれ画像の扱いが異なるので、ここぐらいまで。更に Windows Store, Windows Phone を追加すると、より汎用的になるはずですが、これはあとから。

# github で、ToBitmap を Stream クラスの拡張メソッドにする方法に変えたので、説明も後で変更します。

■サンプルコード

https://github.com/moonmile/XamarinPortableRes

■実行結果


カテゴリー: Android, C#, Xamarin, iOS | Xamarin.iOS/Android で、文字列と画像をPCLを使って共有させる方法 はコメントを受け付けていません

アリスはルイスにプラダを知られたくない

#プログラマが思春期の娘に言われると傷つく一言 – Togetterまとめ
http://togetter.com/li/294232

を見ていて、「お父さんと同じ名前空間に居たくない!」と「パパのコードと一緒にビルドしないで!」が秀逸だったので C# で実現してみました。正確には名前空間じゃなくて Prada というクラス名を見せないようにします(まあ、クラス名をネストの深い名前空間に入れておけば、名前空間自体を探ることも難しいと思うのですが…これはあとで調べてみよう)。

単純に AliceRoom のアセンブリのクラスを他のアセンブリに公開したくない場合は、private なり internal を使えばよいのですが、そうなると Lolita に Prada を渡したく。Lewis(今回はお父さん役)には見せたくないけども、友達の Lolita とは共有したい場合は、InternalsVisibleTo 属性を使ってフレンド共有をします。こうすることで internal クラスが LolitaRoom から見えるという状態になります。

// Lolita クラスにのみ公開する
[assembly: InternalsVisibleTo(&quot;LolitaRoom&quot;)]

namespace AliceRoom
{
    public class Alice : Room.IPerson
    {
        public void Init()
        {
            var bag = new Prada();
            bag.Owner = &quot;Alice&quot;;
            bag.Content = &quot;my secret&quot;;
            this.box = bag;
        }
        public string GetBagContent()
        {
            var bag = box as AliceRoom.Prada;
            if (bag == null)
                return &quot;NONE&quot;;
            else
                return bag.Content;
        }
    }
    /// <summary>
    /// Plada クラスは LolitaRoom にのみ公開
    /// </summary>
    internal class Prada
    {
        // Owner を設定できるのは Alice だけ
        public string Owner { get; internal protected set; }
        // コンテンツは Lolita も取得できる
        public string Content { get; set; }
    }
}

さて、もうひと息やって、Prada オブジェクトを Lolita に渡すことにします。
渡し方をどうするかというと、Alice.Post( Lolita ) みたいに渡したいですよね。実際に渡す Prada オブジェクトは、以下の Main から見えない(公開しているのは LolitaRoom アセンブリのみ)ので、何を誰に渡すのかが必要です。しかし「何を」渡すか自体は、Alice と Lolita しか知らないので、どうやって渡すかは試案のしどころ。

class Program
{
    static void Main(string[] args)
    {
        var alice = new AliceRoom.Alice();
        var lolita = new LolitaRoom.Lolita();
        var lewis = new LewisRoom.Lewis();
        // Pradaを作成
        alice.Init();

        // AliceRoom.Prada は見れない
        Console.WriteLine("alice room : {0}", 
            alice.GetBagContent());
        Console.WriteLine("lolita room: {0}", 
            lolita.GetBagContent());
        // Lolitaに渡す
        alice.Post(lolita);
        Console.WriteLine("alice room : {0}",
            alice.GetBagContent());
        Console.WriteLine("lolita room: {0}",
            lolita.GetBagContent());

        // Lwewis から AliceRoom.Prada は見れない
    }
}

仕方がないので、渡すためのインターフェースを作ります。ここでは、IPerson インターフェースを作って object 型で渡しているのですが、途中シリアライズ化する方法もあります。そういう意味では INotify を使ってもいいと思います。

namespace Room
{
    public abstract class IPerson
    {
        protected object box { get; set; }
        public void Post(IPerson dest) {
            dest.box = this.box;
            this.box = null;
        }
    }
}

あと、Prada の Owner 情報は Alice なので、Lolita が勝手に書き換えてはいけません。クラス情報は Lolita に公開するけど、Prada.Owner.set は Alice だけが使えるように「internal protected set」にしておきます。

namespace LolitaRoom
{
    public class Lolita : Room.IPerson
    {
        public void Post(Room.IPerson dest, object obj)
        {
            this.box = obj;
        }
        public string GetBagContent()
        {
            var bag = box as AliceRoom.Prada;
            if (bag == null)
                return "none";
            else
                return bag.Content;
        }
    }
}

そんな訳で「お父さんと同じ名前空間に居たくない!」を実現したのがこちら。

サンプルコードは github
https://github.com/moonmile/DontLookMyNamespace

カテゴリー: 開発, C# | アリスはルイスにプラダを知られたくない はコメントを受け付けていません

F#のコンピュテーション式をVBAを使って真似してみる…というかDSLの真似

別にコンピュテーション式を調べていたのではなくて、「ひょっとしたらコンピュテーション式とCustomOperation属性で独自の二項演算子がエミュレートできるのでは?」と思っていて探していた訳で、結果的には「できない」なんですが、その派生としてマーチン・ファウラー著のDSL本を斜め読みしたので、その関連で。

32.4 Using Multiple Builders for the calender(Java) のところまで読みながら、局所的なマクロは業務コードを組むと良く出てくるパターンで、lex/yacc まで使わなくても(いや、yacc 使ったほうが手っ取り早いときもあるんですが)アセンブラ風のコマンドが先頭にあってパラメータが続くというパターンは解析がしやすいので、作るのも解釈するのも楽です。それもあって、手軽なものならば1回こっきりの自作コードを作っては捨ててもそんなに惜しくない。と言いますか、そのあたりが「スクリプト」感覚ですよね(最近のLLという意味ではない、昔のスクリプティングという意味で)。

C#やJavaの場合にはメソッドチェーンを使いますが(LINQの場合はクエリ式で並べるというパターンのあるかと)、VBの場合は With というキーワードがあります。

With obj
 .Name = "masuda"
 .Country = "Japan"
End With

みたいな書き方で、obj.Name = “masuda” と羅列する代わりに With obj で囲む方法ですね。C言語の頃は、変数名が長くなると面倒くさいので、

Person *longlonglongobjectname ;
Person *o = longlonglongobjectname;
strcpy( o.Name, "masuda" );
strcpy( o.Contry, "Japan" );

みたいに代入したりします。いや、これだとスタックを消費してしまうから、Person &o = *longlonglongobjectname; な風に参照を使ってみたりする場合もある訳ですが、この手の方法は C# でもよくやります。まあ、C# の場合は、長い変数名とかメソッド名は、インテリセンスを使って記述できるように工夫する方法もよくやりますが。

さて、さっきの With を使う方法は、VB.NET でも使えていて、メソッドにも使えるのですが、VB.NETの場合メソッド呼び出しは必ず括弧が入るので、いまいちスクリプトっぽくないんですよね。そういう点では、F# はスクリプトっぽいし、メソッドチェーンもスクリプトっぽい。見た目は大事です。

じゃあ、どうせ書くならば VBA ということで(VB6でもOK)、メソッドを羅列してスクリプトっぽく書くと、こんな風に書けます。

Option Explicit

Sub test()
    Dim cb As New CalenderBuilder
    With cb
        .Add "DSL tutorial"
        .On__ 2009, 11, 8
        .From "09:00"
        .To__ "16:00"
        .At__ "Aarhus Music Hall"
        
        .Add "Making use of Ptterns"
        .On__ 2009, 10, 5
        .From "14:15"
        .To__ "15:41"
        .At__ "Aarhus Music Hall"
    End With
End Sub

.From とかで羅列していますが、最初の CalenderBuilder オブジェクトに対して With しているだけです。
これを実装するためには、2つのクラス(CalenderEvent、CalenderBuilder)が必要です。

CalenderEvent.cls は単純なデータクラス

Option Explicit

Public Name As String
Public year As Integer
Public month As Integer
Public day As Integer
Public startTime As String
Public endTime As String
Public location As String

CalenderBuilder.cls がビルダークラス

Option Explicit

Public items As New Collection
Public cur As CalenderEvent

Public Sub Add(title As String)
    Set cur = New CalenderEvent
    items.Add cur
    cur.Name = title
End Sub

Public Sub On__(year As Integer, month As Integer, day As Integer)
    With cur
        .year = year
        .month = month
        .day = day
    End With
End Sub

Public Sub From(s As String)
    cur.startTime = s
End Sub

Public Sub To__(s As String)
    cur.endTime = s
End Sub

Public Sub At__(s As String)
    cur.location = s
End Sub

関数名が To__ のようにアンダーバーをつけて伸ばしているのは、スクリプトにしたときにインデントを揃えるためとキーワード逃れです。From, To__ 関数の中身はサボっていますが。

じゃあ、コンピュテーション式風にIfとかWhileを再定義できるかという出来ないわけで、コンピュテーション式とは程遠い訳ですが、DSL には近いかなと思ったり。
DBの初期設定とかヒアドキュメントに書けるのが利点かと思います。コードに直接設定を書くので汎用性はないのですが、むしろ汎用性を無くして設定ファイルが散逸しないメリットを活かせます。

ちなみに、この場合はビルダークラス使わなくても、大抵の場合は以下で書く。
CalenderEvent メソッドのほうに From メソッド等を移動させて、こんな感じ。

Dim obj As CalenderEvent
Dim items As New Collection

With obj
	Set obj = New CalenderEvent
	items.Add obj
    .Name "DSL tutorial"
    .On__ 2009, 11, 8
    .From "09:00"
    .To__ "16:00"
    .At__ "Aarhus Music Hall"
         
	Set obj = New CalenderEvent
	items.Add obj
    .Name "Making use of Ptterns"
    .On__ 2009, 10, 5
    .From "14:15"
    .To__ "15:41"
    .At__ "Aarhus Music Hall"
End With
カテゴリー: 開発 | F#のコンピュテーション式をVBAを使って真似してみる…というかDSLの真似 はコメントを受け付けていません

Xamarin StuidoでF# iOS アプリ(storyboard版)を作る方法

現時点でアルファ版ですが、Xamarin Studio 5.0 だと F# で iOS/Android のアプリが組めます。ただし、現時点では F# プロジェクトのテンプレートが storyboard 無しなので、UI を作ろうとするとコードで書かなくて大変…なのですが、ちょっと工夫するとできました、という例として。
追記 2014/05/14 alpha版のXamarin Studioしか確認してないのですが、アドイン自体は Xamarin Studio 4 のほうでもインストールできます。そうすると、現状でもF# iOSアプリは可能?

サンプルコードは https://github.com/moonmile/XamarinFSharp にあります。

■手順

1.プロジェクトにファイルを追加で「empty iphone storyboard」を追加する。

image

2. 空の storyboard に ViewController を貼り付けて、UI を作る。
3. ViewController のクラスは、*ViewController.fs に設定しておく。
4. アクセスできるように各コントロール/ウィジットに名前を付けておく。
5. 保存をすると、*ViewController.cs と *ViewController.desinger.cs が作られるので、プロジェクトから削除しておく。
6. 対応する Outlet を手作業で *ViewController.fs に書き込む。

 [<Outlet>]
 member val edit1 : UITextField = null with get, set

7. ViewController のコンストラクタを直す。

type XamarinFSharp_iOSViewController ( handler : IntPtr ) =
inherit UIViewController ( handler )

8. AppDelegate.fs を開き Window プロパティを追加する。

 [<Register (&quot;AppDelegate&quot;)>]
type AppDelegate () =
  inherit UIApplicationDelegate ()
  // make Window property
  override val Window = null with get, set

9. Info.plist を開き Main Interface を ‘MainStoryboard’ に設定する。

image

これをビルドして実行すると、C# と同等に動きます。

image

*ViewController.fs のコードを見ると分かるのですが、Outlet 部分が ViewController クラスの本体に入っているので、C# のように partial クラスを作って *.designer.fs に追い出したい訳なのですが、どうもうまくいかないようです。F# で部分クラスを作るのは type … with を使えばいいらしい http://stackoverflow.com/questions/4376275/c-sharp-to-f-convert-public-partial-class-device-marshalbyrefobject のですが、http://msdn.microsoft.com/en-us/magazine/hh394149.aspx を見ると none support みたいです。なんか、Outlet 部分を追い出す方法はないのかな。まあ、あるいは MVVM パターンにしてしまうか。MvvmCross に直すパターンと、Prism.Mvvm を試してみるか。

カテゴリー: F#, Xamarin, iOS | Xamarin StuidoでF# iOS アプリ(storyboard版)を作る方法 はコメントを受け付けていません