酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

.NET Framework APIの型をWindows Runtime APIの型を変換する

本日は、Windowsストアアプリ Advent Calendarの第7日目です。

Windowsストアアプリでは、.NET Framework APIとWinRT APIの両方を混在させて扱うことができます。

仕事柄ダウンロードしてきたファイルを扱ったり画像を扱ったりすることが多いので、System.IO.StreamやWindows.Storage.Stream.IRandomAccessStreamをよく使います。複数のサードパーティのライブラリを扱うことがあればアプリ内で同梱せざるを得ないケースもあるかと思います。

例えば、Windowsストアアプリでは2つのHttpClientクラスが使えます。System.Net.Http.HttpClientクラスでは、ダウンロードしてきたファイルのストリームはSystem.IO.Stream型。Windows.Web.Http.HttpClientクラスでは、ダウンロードしてきたファイルはWindows.Storage.Streams.IBuffer型となっています。

それぞれのライブラリにデータを渡すときには、適切に型が変換されている必要があります。本記事ではよく僕が使っているストリーム、バッファ関係の型の変換について紹介しましょう。

どうでも良い話なのですが、最近ダンガンロンパにハマっています。朝日奈さん、いいよね。

ダンガンロンパ1・2 Reload - PSVita

ダンガンロンパ1・2 Reload - PSVita

さて、本題です。

型を変換する

Stream → IBuffer

System.IO.StreamからWindows.Storage.Streams.IBufferの変換です。

// using System.Runtime.InteropServices.WindowsRuntime;

IBuffer buffer = null;
using (System.IO.Stream strm = GetStream())
using (var reader = new System.IO.BinaryReader(strm))
{
    var bytes = new byte[strm.Length];
    reader.Read(bytes, 0, bytes.Length);
    buffer = bytes.AsBuffer();
}

IBuffer → Stream

Windows.Storage.Streams.IBufferからSystem.IO.Streamの変換です。

// using System.Runtime.InteropServices.WindowsRuntime;
// using Windows.Storage.Streams;

System.IO.Stream stream = GetStream();

// ストリームからデータを読み込む
var bytes = new byte[stream.Length];
stream.Seek(0, System.IO.SeekOrigin.Begin);
await stream.ReadAsync(bytes, 0, bytes.Length);

IBuffer buffer = bytes.AsBuffer();

byte[] → IBuffer

byte型配列からWindows.Storage.Streams.IBufferの変換です。

usingディレクティブにSystem.Runtime.InteropServices.WindowsRuntimeを宣言しておくことによって拡張メソッドが使用できるようになります。

byte型配列の拡張メソッドのAsBufferメソッドを使ってIBufferへ変換します。

// using System.Runtime.InteropServices.WindowsRuntime;

byte[] bytes = GetXXXXX();

IBuffer buffer = bytes.AsBuffer();

IBuffer → byte[]

Windows.Storage.Streams.IBufferからbyte型配列の変換です。

IBufferクラスの拡張メソッドであるToArrayメソッドを使ってbyte型配列へ変換します。

IBuffer buffer = GetXXXXX();

buffer.ToArray();

byte[] → IRandomAccessStream

byte型配列からWindows.Storage.Streams.IRandomAccessStreamの変換です。

// using System.IO;
// using Windows.Storage.Streams;
// using System.Runtime.InteropServices.WindowsRuntime;

// byte型配列をIBufferへ変換する
var buffer = bytes.AsBuffer();

var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
await stream.WriteAsync(buffer);
return stream;

Windows.Storage.Streams.IRandomAccessStream → byte[]

Windows.Storage.Streams.IRandomAccessStreamからbyte型配列の変換です。

IRandomAccessStreamクラスのReadBytesAsyncメソッドを使ってbyte型配列を読み込みます。

// using System.IO;
// using Windows.Storage.Streams;

IRandomAccessStream stream = GetXXXXX();

var bytes = await stream.ReadBytesAsync();

Stream to IRandomAccessStream

System.IO.StreamからWindows.Storage.Streams.IRandomAccessStreamの変換です。

Windowsストアアプリでは、System.IO.WindowsRuntimeStreamExtensionsクラスが提供されています。このWindowsRuntimeStreamExtensionsクラスを使って、ストリーム関係の変換を非常に簡単におこなうことができます。

System.IO.Stream型のストリームからWindows.Storage.Streams.IRandomAccessStream型のストリームへ変換するには、AsRandomAccessStreamメソッドを使います。

// using System.IO;
// using Windows.Storage.Streams;

Stream stream = GetXXXXX();
var ras = WindowsRuntimeStreamExtensions.AsRandomAccessStream(stream);

IRandomAccessStream to Stream

Windows.Storage.Streams.IRandomAccessStreamからSystem.IO.Streamの変換です。

IRandomAccessStreamクラスのReadBytesAsyncメソッドを使ってbyte型配列bytesにデータを読み込み、bytesの内容をMemoryStreamストリームに書き出します。

// using System.IO;
// using Windows.Storage.Streams;

IRandomAccessStream stream = GetXXXXX();

var bytes = await stream.ReadBytesAsync();
var memStream = new MemoryStream())
memStream.Write(bytes, 0, bytes.Length);

あとがき

Windowsストアアプリ開発において、System.Runtime.InteropServices.WindowsRuntime名前空間のWindowsRuntimeBufferExtensionsクラスと、System.IO名前空間のWindowsRuntimeStreamExtensionsクラスはとても便利です。

ただいまメンテナンスしているストアアプリでは、それぞれの拡張メソッドを知らない時代のコードが混じっていて苦労した跡を伺うことができます。開発効率がとても向上しますので、いつかこれらを使う日のためにこれらの拡張メソッドが存在していることだけでも覚えておいてくださいね。

Windowsストアアプリを開発している人はみんな知ってそうな気もする。この辺りのことは依然書いた書籍でも取り上げています。もしWindowsストアアプリの開発で困ることがあれば、「Windows8ストアアプリ開発入門」と「Windowsストアアプリ開発のレシピ110」をお読みください。

今までWindowsストアアプリの開発をしたことがない方であれば前者の「Windows8ストアアプリ開発入門」をお読みください。

Windows8ストア アプリ開発入門

Windows8ストア アプリ開発入門

もうすでにWindowsストアアプリの開発をしていて、大まかには知っているので逆引き的に調べたいという方であれば後者の「Windowsストアアプリ開発のレシピ110」をお読みください。

Windowsストアアプリ開発のレシピ110

Windowsストアアプリ開発のレシピ110

それでは、楽しいWindowsストアアプリ開発を!

追記

応用編もあるよ!

関連記事

Windowsストアアプリ(WinRT API)を使ってアプリ開発する際に逆引きとしてお使いください。

blog.ch3cooh.jp