Posts

Showing posts from September, 2009

Windows Forms 入力検証 - Disable にした TextBox の入力検証を抑制する

Image
ボタンクリック時の入力検証などにしようする Form.ValidateChildren()。 Form 内の全コントロールの検証を行うメソッドなのだが、時に検証して欲しくないコントロールまで検証を実行してしまう。例えば、ラジオボタンによってテキストボックスの一部が Disable になったりする場合、ValidateChildren() を呼ぶと Disable のテキストボックスの検証も走ってしまう。 この動作は、ValidationConstraints 型の引数をとる ValidateChildren() のオーバーロードメソッドで制御することが可能。Disable のテキストボックスの入力検証を行わない場合は ValidateChildren(ValidationConstraints.Enabled) とする。個別のコントロールのプロパティや Validating イベントハンドラでは特に何もする必要がない。

Windows Forms 入力検証 - エラー項目のフォーカスをロックしないパターン

Image
今回は、コントロールに入力エラーがある場合もフォーカスをはずせるように実装するパターン。 要件 前回と同じくこういう画面を考える。 この画面を作る上で、このような要求があるとする。 TextBox に必須入力チェックを実装する。ただし、エラーがある場合も TextBox からフォーカスがはずせるようにする。 Register ボタンをクリックした際、画面の全項目の入力チェックを実施し、エラーがあった場合は処理を中止する。 TextBox に入力エラーがある状態でも、閉じるボタン (タイトルバー右の) が機能する。 実装 以下のようにプロパティとイベントの設定を行う。 Form の設定 入力エラー時にもフォーカスをはずせるように実装する場合、ポイントは Form の AutoValidate プロパティです。このプロパティの値を EnableAllowFocusChange に変更すれば、入力エラーがあっても、フォーカスがはずれるようになります。 ただし、AutoValidate を変更しても、入力エラーがあるコントロールにフォーカスが当たっている状態でタイトルバーの閉じるボタンを押した場合、自動的に Close をキャンセルされてしまいます。これを回避するためには、OnFormClosing() をオーバーライドして、e.Cancel = false にします。 protected override void OnFormClosing(FormClosingEventArgs e) { base.OnFormClosing(e); e.Cancel = false; } TextBox の設定 TextBox の入力検証を行う処理を実装する。Validatingイベントハンドラの実装は、フォーカスをはずせなくする場合とまったく同じで、入力エラーがある場合には e.Cancel = true を設定する。ただし、Form の設定により、e.Cancel に true を設定してもフォーカスははずれる。 private void ValidateTextBoxIsNotEmpty(object sender, CancelEventArgs e) { TextBox t

Windows Forms 入力検証 - エラー項目のフォーカスをロックするパターン

Image
これまでの経験上、画面の単項目入力検証のコードは汚くなりがちなところの1つだ。Windows Forms が提供している機能に対する知識不足のせいで、どうしても無理やり仕様を満たすためのトリッキーなコードを書いてしまうことが多い。そんなことをしているので、後々の障害対応や仕様変更のときにイヤな思いをするはめに... そこで、Windows Forms の入力検証について、要件毎に実装パターンをまとめようと思う。まずは、入力エラーがあるコントロールからフォーカスをはずせないように実装するパターン。 要件 こんな画面を考える。 この画面を作る上で、このような要求があるとする。できるだけコードが汚くならないように、この画面を実装したい。 TextBox に必須入力チェックを実装し、エラーがあった場合は TextBox からフォーカスがはずれないようにする。 Register ボタンをクリックした際、画面の全項目の入力チェックを実施し、エラーがあった場合は処理を中止する。 TextBox に入力エラーがある状態でも、Cancel ボタンと閉じるボタン (タイトルバー右の) はクリックできる。 実装 以下のようにプロパティとイベントの設定を行う。 TextBox の設定 TextBox の入力検証を行う処理を実装する。入力エラーがある場合、e.Cancel に true を設定することで、フォーカスがはずれなくなる。 private void ValidateTextBoxIsNotEmpty(object sender, CancelEventArgs e) { TextBox textBox = (TextBox)sender; if (String.IsNullOrEmpty(textBox.Text)) { this.errorProvider1.SetError(textBox, "This text box must have value."); e.Cancel = true; } else { this.errorProvider1.SetError(textBox, St

strfriend で正規表現を可視化する

Image
他人が書いた正規表現を解読するのは大変な作業だが、そんな苦痛を少しだけやわらげてくれるオンラインサービス、 strfriend なんていうものがある。 正規表現を入力すると、そのパターンを図示してくれる。

Google AJAX API チームの Google Chrome Frame 検出 API

Google AJAX API チームのブログ で、Google Chrome Frame 検出用 API を作成中、とアナウンスされていた。 Google AJAX APIs Blog: Google Chrome Frame Ajax Detection Google Chrome Frame がインストールされているかどうかを確認できるので、されていなければインストールを促す、あるいは Google Chrome Frame の有無によって細かい制御を行うといったことが可能になります。 シンプルデモページ で使用例を見ることができる。   Web アプリケーションを作る側からすると、テストケースが増えるので Google Chrome Frame に対して諸手を挙げて大賛成できないのだが、あの IE で HTML5 やハイパフォーマンスの JavaScript エンジンを使えるようになるのは、ユーザーとしてはありがたい。 大手のサイトが対応し始めて、雑誌か何かで「Google Chrome Frame で IE を早くする」みたいな特集が組まれたら、一気に Google Chrome Frame 人口が増えそうだ。IE は使い慣れてるから別のものにはしたくないんだけど遅くて... と思っている人は多いはず。

Web.config Security Analyzer 使ってみた

Image
Web.config の脆弱性を検出するツール Web.config Security Analyzer (wcsa) の GUI 版を使ってみた。web.config を読み込ませると、こんなレポートが出てくる。   脆弱性検証ルール 今のところこんなルールが定義されている。 デバッグが無効になっているか Form 認証のパスワードが暗号化されているか カスタムエラーが有効になっているか クッキーレス認証が無効になっているか 認証クッキーを SSL で送信するようになっているか 認証クッキーがユニークになるように考慮しているか スライド式有効期限が無効になっているか クッキーパスに制限を加えているか (‘/’ 以外を設定しているか) 別の Web アプリケーションへのリダイレクトが無効になっているか 暗号化されていないクッキーを拒否しているか 検証されていないクッキーを拒否しているか クライアントのスクリプトからクッキーへのアクセスが無効になっているか ViewState が有効になっているか ViewState のメッセージ認証チェックが有効になっているか ViewState が暗号化されているか リクエストの検証が有効になっているか RoleManager が管理するクッキーを SSL で送信するようになっているか RoleManager が管理するクッキーのスライド式有効期限が無効になっているか RoleManager が管理するクッキーの暗号化が有効になっているか RoleManager が管理するクッキーの検証が有効になっているか RoleManager が管理するクッキーパスに制限を加えているか クッキーレスセッションが無効になっているか トレースが無効になっているか コードアクセスセキュリティレベルが Minimal になっているか Web.config にユーザー情報が定義されていないか   検証ルールとその適用方法 ルールは全て外部 XML ファイルとして定義されており、このファイルに どの要素の

WebsiteSpark : Web アプリ開発に必要なソフトウェアが 3 年無料に

Scott Guthrie 氏のブログ で WebsiteSpark のローンチがアナウンスされた。Web アプリケーションの開発をやっている小さな企業を補助するためのプログラムで、開発に必要な下記のソフトウェアを 3 年間無料で使えるとのこと (プログラム参加手数料が 100 ドルかかる)。 Visual Studio 2008 Professional を 3 ライセンス Expression Studio 3 (Expression Blend、Sketchflow、Web を含む) を 1 ライセンス Expression Web 3 を 2 ライセンス Windows Web Server 2008 R2 を 4 プロセッサライセンス SQL Server 2008 Web Edition を 4 プロセッサライセンス DotNetPanel コントロールパネル ちなみに Windows Server と SQL Server のライセンスは開発もデプロイも可能。3 年たった後は、使うのをやめても良いし、年間 999 ドルパッケージでこれらのソフトウェアを購入しても良いし、プロダクションサーバーライセンスだけ年間 199 ドルで買っても良いそうだ。 プログラムへの参加資格はこの2つの条件を満たしていること。 自社以外のために Web サイトや Web アプリケーションを作っている 社員数が 10 人未満

wcsa : web.config のセキュリティチェックツール

Google Code で wcsa (web.config security analyzer) というプロジェクトを見つけた。 名前の通り、web.config の脆弱性分析ツールで、30 以上のセキュリティチェック機能、詳細レポートの生成機能があるようだ。実行には .NET 3.5 が必要とのこと。 使ってみたらどんな感じか報告しようと思う。

Google Chrome Frame がリリースされた

Chromium Blog より 。 サマリーのところで Google Chrome Frame は「IE に HTML5 やオープンウェブテクノロジーをもたらすプラグイン」だと説明されている。HTML5 の canvas タグのサポートや JavaScript のパフォーマンス改善などの恩恵が得られる。 Google Chrome Frame をインストール後、 <meta http-equiv="X-UA-Compatible" content="chrome=1"> がついた Web ページを開くと Google Chrome Frame が起動して、WebKit ベースのレンダリングエンジンがページのレンダリングをする。Google Chrome Frame 対応のページを表示すると、皮だけ IE で中身は WebKit ということになるようだ。

.NET 4 BCL の新機能 (4) : メモリマップドファイル

メモリマップドファイルは、巨大なファイルの編集や、プロセス間通信のための共有メモリの作成を可能にする新機能。プロセスのアドレス空間をファイルにマップし、その後はメモリを読み書きしたり、ファイルのコンテンツを編集したりできる。ファイルは OS のメモリ管理機構を通じてアクセスされるので、自動的に多くのページに分割される (必要に応じてページイン/ページアウトされる)。開発者自身でメモリを管理する必要がなくなるので、巨大なファイルを簡単に扱えるようになるし、ファイルに完全にランダムアクセスできるようにもなる。 メモリマップドファイルを使うためには、MemoryMappedFile クラスの以下のメソッドで MemoryMappedFile クラスのインスタンスを作る (このクラスは System.IO.MemoryMappedFiles 名前空間にある)。 CreateFromFile CreateNew CreateOrOpen OpenExisting インスタンスを生成したら、CreateViewStream メソッドや CreateViewAccessor メソッドで、実際にファイルとアドレス空間をマップするためのビューを作る。CreateViewStream メソッドではシーケンシャルアクセス用の Stream が得られる (.NET の一般的な Stream と同じように使用可能)。CreateViewAccessor はランダムアクセスが可能な MemoryMappedFileViewAccessor クラスのインスタンスを返す。   サンプルコード メモリマップドファイルを使ったプロセス間通信のサンプル。まず下のコードで mymappedfile という名前をつけたメモリマップドファイルを作成し、”Hello World!” を書き込んだ後、別プロセスを立ち上げている。 using (varmmf = MemoryMappedFile.CreateNew( "mymappedfile" , 1000)) { using ( var stream = mmf.CreateViewStream()) { var writer = ne

.NET 4 BCL の新機能 (3) : SortedSet

.NET 4 BCL にはユニークな要素を保持するコレクション SortedSet が追加される。.NET 3.5 で追加された HashSet のようなものだが、SortedSet の方は名前からも想像がつく通り、各要素はソートされた状態でコレクション内に保持される。 赤黒木 ( 原文 では self-balancing red-black tree。なお、赤黒木についてはざっと検索した限り このページ が詳しく書いてある) で実装されているので、挿入、削除、検索の計算量は O(log n)。一方、HashSet は O(1)。ということで、通常は HashSet を使った方がいいようだ。ただし、 コレクション内の要素をソート状態にしておきたい 特定の範囲のサブセットを取り出したい 最小、最大の要素を取り出したい などの要求がある場合は SortedSet を使うとよいとのこと。   コードサンプル // これで set1 の中身は 1, 2, 4, 5, 6, 8 になります。 // 2 を2回追加していますが、2度目の追加は無視されます。 var set1 = new SortedSet< int >() { 2, 5, 6, 2, 1, 4, 8 };   // プロパティで最小、最大要素を取り出せます。 var min = set1.Min; var max = set1.Max;   // サブセットの取り出しも可能です。subset1 の中身は 2, 4, 5, 6 です。 var subset1 = set1.GetViewBetween(2, 6);   補足 GetViewBetween メソッドで得られるサブセットは面白い性質を持っている。オリジナルの「ビュー」なので、サブセットを変更するとオリジナルにも変更が反映されるのだ。また、境界外のデータを追加しようとすると例外が発生する (上のサンプルの場合は 2 から 6 の範囲でサブセットを取得しているので、例えば 9 を追加すると例外が発生する)。

.NET 4 BCL の新機能 (2) : ファイル IO の改善

.NET 4 では System.IO の読み込み系 API が改善され、遅延ロード用メソッドが追加されるらしい。 例えば File クラス。ReadAllLines というメソッドがあるが、メソッドを呼び出した時点でファイル内の全データをバッファリングするので、巨大なファイルを読み込むと return まで結構待たされることになる。この問題を解決するために、同様の処理を行う ReadLines メソッドが追加された。ReadLines は IEnumerable<string> を返すが、呼び出した時点ではデータを読み込まず、foreach などでデータを使おうとした際に初めてデータの読み込みを行う。 試しに 50 万行のテキストファイルを読み込んで、List<string> に各行を Add するプログラムを作って、ReadAllLines と ReadLines の処理時間を比較した。return が早い分、処理時間に多少コストがかかるかもと思いきや、全然そんなことはないようだ。   ReadAllLines ReadLines return までの時間 0.4 から 0.47 秒 0.02 から 0.1 秒 全行バッファリングまでの時間 0.67 から 0.74 秒 0.36 から 0.73 秒 DirectoryInfo クラスにも EnumerateFiles というメソッドが追加された。これも ReadLines と同じく IEnumerable<FileInfo> だけ return しておき、データを使う時に初めてファイルシステムからファイルの情報を取得する。 LINQ と一緒に使うと特に効果的だ。下のコードは MSDN マガジン に載っているもので、C:\logs フォルダにある拡張子 log のファイルから、Error: で始まる行だけを抜き出す処理。新 API を使うと、フォルダの全ファイルを取得する必要も、ファイルの全行を読み込んでくる必要もなく、条件にあったファイル、行だけが e

Gallio と MbUnit が v3.1 に

Gallio と MbUnit の v3.1 がリリースされた。新機能は ビデオキャプチャとテストレポートへの埋め込み RSpec .NET 4 のサポート Vsial Studio 2010 Beta 1 のサポート コントロールパネルアプリケーション 新しいプラグインモデルの採用と、それに伴う起動時のパフォーマンスの改善 内部デザインの変更 MbUnit の改善 MbUnit は RowTest ができるので前に少しだけ使っていたが、NUnit に比べて粗削りな感じがしたのと、NUnit にも RowTest 拡張があることを知ったので、最近はすっかりご無沙汰になっている。 ただ、ビデオキャプチャの機能が気になる。

CLR オブジェクトヘッダーの構造

Image
前の投稿 で Andrew Hunter 氏の “ Object Overhead: The Hidden .NET Memory Allocation Cost ” を和訳した。その時、オブジェクトヘッダーという単語が出てきたのだが、何なのかよくわからなかったので調べてみた。 本棚を漁ったところ、 Essential .NET に載っていた。実行時のメモリ内はこういう構造になっているとのこと (ただし、x86 の CLR 1.0 の動作を観察して得た結論らしい)。 オブジェクトヘッダーには同期ブロックのインデックスと型のハンドルの2つのフィールドがあって、多分インデックスが int、型ハンドルがポインタなので、オブジェクトヘッダーのサイズは 4 バイト + 4 バイト = 8 バイトなんでしょう。 ちなみに、同期ブロックのインデックスというのは ロックや COM オブジェクトなどの追加リソースをこのオブジェクトと関連付けるために利用 するものなんだそうです。 型のハンドルというのは、図で示されている通り、オブジェクトの実際の型を現す型構造体へのポインタです。

.NET 4 BCL の新機能 (1) - 新機能一覧

MSDN マガジン 2009 年 9 月号 に .NET 4 Beta 1 の BCL に新しく追加されたものについてのカラム ” What’s New in the Base Class Libraries in .NET Framework 4 ” が掲載されていた。 この投稿では新機能の一覧だけ掲載しておく。 コードコントラクトのサポート 並列処理の拡張 (タスク、並列コレクション、協調データ構造) タプルのサポート ファイル IO の改善 メモリマップドファイルのサポート SortedSet コレクション 任意の大きさの整数のサポート インターフェース、デリゲートでの Generic variance annotation 32 ビット、64 ビットレジストリビューへのアクセスと揮発性レジストリキーの作成のサポート グローバル化データ更新 リソース検索フェイルバックロジックの改善 圧縮の改善 Beta 2 ではさらにいくつかの機能を追加しようと思っているらしい。   これらについて勉強したら、個別の機能についてサマリーを投稿する予定。

目には見えない .NET のメモリアロケーションコスト

Simple Talk に興味深い記事が掲載されていた。 Andrew Hunter 氏が書いた “ Object Overhead: The Hidden .NET Memory Allocation Cost ”。以下はその和訳。 オブジェクトの保持には思いのほか多くのメモリが使われます (32 ビットか 64 ビットかによって違いますが)。32 ビットのシステムでは、各オブジェクトは 8 バイドのオブジェクトヘッダーを持ち、さらにどこかからの参照 (4 バイトのポインタ) が必要です。つまり、単純にオブジェクトが存在するだけで 12 バイト必要になります。 64 ビットだと状況はもっと悪くなります。16 バイトのオブジェクトヘッダーに 8 バイトのポインタ。オブジェクトが存在するためだけに 24 バイト必要です。小さなオブジェクトを大量に持っているようなアプリケーションの場合、32 ビットから 64 ビットへの切り替えはひどい状況をもたらすことでしょう。メモリ不足ということにはならないかもしれませんが、要求されるリソースは 3 倍に増えてしまいます (訳注:12 バイトから 24 バイトなんだから 2 倍では?)。 このオーバーヘッドによって .NET アプリケーションにオブジェクト数の制限が課されます。32 ビットシステムではオブジェクトが存在するためだけに 12 バイト必要であり、これは最大オブジェクト数は 1 億 7000 万くらいであることを意味します。しかし、これでは多くのオブジェクトは無価値です。これらのオブジェクトにはデータを持っていないのですから。4 バイトのデータを持たせると、最大オブジェクト数は 1 億 3000 万に減ります。この時、アプリケーションによって使用されているメモリの 75% はオーバーヘッド分であり、非常に非効率的です。 ここで、望ましい効率について考えてみます。.NET インフラによって消費されるメモリ量は、オブジェクトの数と平均サイズから算出することができます。例えば、オーバーヘッドを 10% にするためには、32 ビットシステム上のオブジェクトは平均 80 バイトのデータを保持しなければなりません(この時の合計サイズは 88 バイト。8 バイトのヘッダーは全体の 10% を占めるこ

5 分間で MVVM を概観する

Image
Data-Driven Services with Silverlight 2 という本を書いている John Papa 氏のブログ で「 5 Minute Overview of MVVM in Silverlight 」という役に立つ投稿があったので共有。 イントロダクションで、「多くの記事は MVVM が何か知っていることを前提に書かれているけれど、この投稿は MVVM 自体の簡単な説明です」と書かれている。今まさに注目されている技術というのは、知っている人たちでどんどん議論が進んでいって新参者は追いつくのが大変なので、こういう基本を勉強できるコンテンツはありがたい。 View View はユーザーインターフェースを表すクラスです。例えば Silverlight では MainPage.xaml や Page.xaml です。View はコントロール、アニメーション、ナビゲーション、テーマ、その他表示用の対話機能を持っています。Silverlight や WPF ではデータバインディングも View に含まれます。バインディングはデータのどのプロパティを使うかだけを指定していて、プロパティがどこからくるのか (つまりどのインスタンスにバインドされるのか) は意識していません。データソースが View の DataContext にセットされた時に、バインディングがアクティブになります。 View に関する別の意見 XAML 内のリソースで ViewModel を作って View にアサインすることがあります。私は View と ViewModel を分離して連携させる方が好きです。でも、リソースとして View の中で ViewModel を作るのはとてもポピュラーなようです。どちらの方法もいいところがあります。View の中で ViewModel を作ってしまうのは Blend を使う場合に簡単で効率がいいでしょう。View と ViewModel が疎結合であれば DI しやすさやテスタビリティを高めます。 Model 特定のエンティティとして表現されるデータを表すクラスです。例えば、CompanyName や CustomerId のようなプロパティを持った Customer クラスです。Cust

データは物理的にも論理的にも削除すべきではないのか?

InfoQ Japan に昨日 (9/13) づけで データの削除は非推奨 というニュースが公開された。内容をまとめると Oren Eini 氏曰く : 論理削除はデータが間違いを含んだ状態(例えば顧客エンティティが論理削除された注文エンティティを保持する)になりやすいよね。論理削除はやめた方がいいよ。 じゃあ、物理削除することにして、整合性を保つためにカスケード削除すればいいか。 Udi Dahan 氏曰く : いやいや、現実世界ではカスケード削除されないよ(カタログに載っている商品を「削除」しても商品自体への注文は一緒に消えてなくなることなんてない)。そもそも、現実世界で行われることは「削除」の一言では表しきれないじゃない。注文は削除じゃなくてキャンセルされるものだし、従業員は解雇とか退職、仕事は完了とか取り消しだよね。単純な IsDeleted フラグじゃなくて、有効、中止、キャンセル、廃止予定のような状態を持たせるべきじゃないかな。 つまり、物理削除も論理削除もしないほうがいいんじゃない?という話だ。   今の仕事について以来、関わったシステムはほとんど論理削除で設計されていたので、業務システムは論理削除が普通なんだと思って受け入れていたが、言われてみれば確かにそうかとも思う。データベースが、現実世界の情報をモデル化してシステム上で再現したものと考えれば、データの「削除」についても現実世界に即したものにすべきではないか。 僕の周りは論理削除が多いが、実際のところどうなのだろう? 現実に論理削除が多いのは、単純に Udi Dahan 氏のような視点がなかっただけなのか、それとも論理削除にメリットがあるのか?

Silverlight では XAML で Nullable 型プロパティに値を設定できない

Silverlight の XAML パーサーは、Nullable 型プロパティへの値設定に対応していないらしい(試したのは Silverlight 3)。XAML で Nullable 型プロパティに値を設定しようとすると、実行時に System.Windows.Markup.XamlParseException が発生し、 "AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 8 Position: 60]" という意味不明のエラーメッセージだけが表示される。ちなみにパースの失敗なので、クラスに Nullable 型のプロパティが宣言してあっても、値を設定していなければ問題ない。 これに限らず、XAML 関係の例外(パースエラーとか)のメッセージをもっとわかりやすくしてもらえるとありがたい。WPF は当初に比べるとだいぶよくなってきたが、Silverlight はまだこのような意味不明メッセージが多いという印象を持っている。

LINQ を使って差集合を取得する

Image
Microsoft Visual Studio プログラムマネージャの Noah Coad 氏のブログ で 面白い投稿 を見つけた。 差集合取得操作をしたいと思うことが時々あるでしょう。つまり、集合 A の要素の中で集合 B に存在しないものだけを取得するという操作です。集合 A と B の型が同じであれば LINQ の Except メソッドでこれを実現できるのですが、集合の型が異なり、かつ ID をマッチさせなければならないということがよくあります。ここでは LINQ を使ってどうやってこれを実現するかという簡単な例をご紹介します。 Wolfram MathWorld によれば操作はこのように定義されます: private static void Main( string [] args) { List< string > names = new List< string > { "Noah" , "Sarah" , "Josiah" , "Craig" , "Carolin" }; Dictionary< string , string > visiting = new Dictionary< string , string >() { { "Noah" , "Turkey" }, { "Craig" , "Germany" }, { "Sue" , "Bangalore" } }; var minus = from n in names let places = from p in visiting select p.Key where !places.Contains(n) select n; foreach ( var v in minus) { Console.WriteLine(v); } Conso

WPF のレイアウトシステムに連動する Web ブラウザコントロール

Image
Chris Cavanagh という方が Google の Chromium とか、 Awesomium をベースに、WPF の Web ブラウザを作っている。 Chris 氏によれば WPF で Web ページをレンダリングし、Web ページと連携できるようにすることは大きく可能性を広げます。WPF には WebBrowser コントロールが組み込まれていますが、これは IE の ActiveX コントロールのラッパーであり、残念ながら WPF レイアウトシステムに連動しません。 というのがモチベーションになっているらしい。確かに、WebBrowser コントロールは TextBox や Button などの一般的なコントロールに比べてちょっと特殊(例えば Opacity が効かない)な挙動をするので、レイアウトシステムときちんと連動してくれる WebBrowser ライクなコントロールがあるとありがたい。 ちなみに、すでにデモアプリを試すことができる。下のスクリーンショットは このページ からダウンロードしたもの。見ての通り、ブラウザ画面に WPF のエフェクトをかけることができている。 これは YouCube という名前の WPF 3D Web ブラウザ。 このページ からデモアプリをダウンロードできる。

外部フォルダのアセンブリを動的にロードする

アプリケーションがおいてあるフォルダの外にあるアセンブリを、カレント AppDomain に動的にロードする方法。 Dynamic Loading of .Net Assemblies ロードしようとしているアセンブリが見つからない場合に AppDomain.AssemblyResolve イベントが発生するので、このイベントのハンドラで追加のアセンブリロード処理を実装すればよい。 public class Bootstrap { private static void Main( string [] args) { AppDomain.CurrentDomain.AssemblyResolve += SearchAssemblyFromDirectories; string [] directories = new string [] { @"C:\asm" }; AppDomain.CurrentDomain.SetData( "directories" , directories); Assembly asm = Assembly.Load( "MyAssembly" ); foreach (Type type in asm.GetTypes()) { Console.WriteLine(type.FullName); } Console.ReadKey(); } private static Assembly SearchAssemblyFromDirectories( object sender, ResolveEventArgs e) { string [] directories = ( string [])AppDomain.CurrentDomain.GetData( "directories" ); foreach ( string dir in directories) {

WPF/Silverlight の Canvas 内のコントロールを動的にレイアウト変更する

Image
こんなことをやろうとしている。 (1) Window や Page から CanvasLayoutManager に対して状態遷移を指示する。この時、次の状態の名前を指定する。 (2) CanvasLayoutManager が指定された状態のレイアウトを取得し、現在のレイアウトと遷移後のレイアウトの情報をマージする。 (3) アニメーションを使って Canvas 内のレイアウトを変更する。 つまり各コントロールのレイアウト情報を外だしで定義しておいて、それを状態という形でグループ化して複数定義できるようにし、状態を切り替えることで動的なレイアウト変更を可能にしようとしています。 状態を各状態を保持した CanvasLayoutDefinition は XAML 内にリソースとして記述することを想定している。レイアウトには各コントロールのサイズ、位置、透明度を指定できるようにしていて、サイズと位置は Canvas のサイズと Canvas 内の相対位置をもとに割合で指定できるようにと考えている(例えば、Top=0.5、Left=0.5、Height=0.3、Width=0.3 と指定したら、コントロールの左上が Canvas の真ん中に来てサイズは Canvas の 0.3 倍になる)。 WPF 版の実装は大体できていて、これから Silverlight にポーティングしようとしている。完成したら CodeProject で公開予定。

Doloto : Web 2.0 アプリケーション最適化ツール

Image
MSDN DevLabs のフィードを流し読みしていたら “ Doloto ” が目を引いたので、少し調べてみた。 Doloto は AJAX を使ったアプリケーションを最適化するツール。アプリケーションから JavaScript を分離してスタブに置き換え、最初にページを表示する時にロードする JavaScript コードの量を減らすことで、初期表示時間を短縮する。実際の JavaScript コードは、最初に実行しようとしたタイミングでダウンロードされる。 それから、 Somasegar 氏のブログ に Doloto の実行手順が書かれている。 Doloto はスタンドアローンのクライアントサイドツールで、次の3つのステップで動作します。 アプリケーションをプロファイリングします。Doloto はローカルプロキシを実行してプロファイリングを行い、JavaScript をインターセプトして、ブラウザに依存しない方法で各 JavaScript 関数の実行時のタイムスタンプを取得できるようにします。 プロファイリング情報はコードカバレッジとクラスタリング戦略を見積もるために使われます。これは関数をスタブ化するのか、もしくはまとめてダウンロードされるようにグルーピングするのか(クラスタと呼ばれます)を決定します。 JavaScript コードを書き換えます。ローカルディスクに保存されるので、それをサーバーにアップロードしてください。全ての処理はサーバーにアクセスせずに、ローカルマシン内で実行されます。そのため、サードパーティのサイトを、それらのサーバーにアクセスせずにプロファイリングし、最適化できます。Doloto の処理結果に満足できた時点で、サーバーにファイルをデプロイすることができます。 また、同じく Somasegar 氏のブログ に Doloto の最適化の結果が掲載されている。 我々が行った多くの AJAX アプリケーションへのアクセス実験の結果、Doloto は JavaScript コードの初期ダウンロード量を 40% 以上減らし、アプリケーションの立ち上がりを 30 ~ 40% 高速化しました(ネットワークの条件に依存しますが)。このグラフは、ポピュラーな Web サイ

ソースコードに色付けするためのライブラリ ColorCode 1.0 リリース

CodePlex でソースコードをスタイル設定済みの HTML に変換するライブラリ ColorCode のバージョン 1.0 が公開された。ちょうど C# でこういうことをやりたいと思っていて、気になったので共有。 サポートされている言語は XML JavaScript SQL C# VB.NET ASPX (C# & VB.NET) C++ PHP 使い方は非常にシンプル。 using ColorCode; using System; using System.IO; namespace ConsoleApplication1 { class Program { static void Main( string [] args) { string source = File.ReadAllText( @"C:\tmp\Program.cs" ); CodeColorizer colorizer = new CodeColorizer(); string result = colorizer.Colorize(source, Languages.CSharp); File.WriteAllText( @"C:\tmp\Program.htm" , result); } } } ちなみに、ここに貼ったコードはこのサンプルプログラムの実行結果(フォントファミリーだけ等幅に変えたが)。C# しか試していないが、型の色以外は Visual Studio のデフォルトカラーとほぼ同じになった。

30 秒で単体テストの問題点を探し出す8つのテクニック

Roy Osherove 氏の投稿 “ 8 techniques to find problems in your unit tests within 30 seconds ” より。 信頼性の点から テストプロジェクトで “DateTime.” を使っているところを探してください。 DateTime を使っているということは、本質的に毎回異なる単体テストを走らせていることになります。もし DateTime が原因でテストが失敗し、その時使われた値のログをとっていなければ、失敗を再現するのは困難でしょう。 テストプロジェクトでスレッドを使っているところを探してください。 スレッドを使っていると、ロジックではなくスレッドのせいでテストが失敗してしまうでしょう。低スペックマシンやマルチ CPU のマシンで動かした時さえ、テストの動きが変わります。結合テストならよいのですが、常に同一の結果になる必要のある単体テストにとっては問題です。 “Environment.” を探してください(newline は除いて)。 現在の環境に依存したものを使っている場合、2つのことが起こりえます。テストマシンが変わると異なるテストをすることになり、テストはプロダクションコードの中のロジックを繰り返します。代わりに、環境変数のフェイクを使い、期待値をテストコード内にハードコーディングすべきです。そうでなければ、結合テストをすべきです。   メンテナンス性の点から Resharperを使って “.Verifiable” メソッドを探し、メンバーでグルーピングしてください。 この時、テスト毎に1つであるべきです。そうでなければ、1つ以上のことについてテストしていることになります。そして、内部動作を過度に指定しているのでより脆弱なテストになってしまっています。コードの変更があったら、テストはすぐに動かなくなってしまいます。 Moqを使っているなら、".VerifyAll”を探してください。 これも内部動作の過度な指定で、テストを脆弱で失敗しやすいものにしてしまいます。検証は1つのモックオブジェクトだけにすべきです。 Rhino Mocks を使っているなら、AssertWa

ADO.NET Data Services CTP1 と CTP2 の比較

Marcelo 氏のブログ で ADO.NET Data Services CTP1、2 の機能比較表が公開されている。 Marcelo 氏の投稿 によれば、CTP2 で新しくなったのは以下の点とのことだ( ADO.NET Data Services Team Blog の情報をもとに一部補足)。 機能 CTP1 で使える? CTP2 で新しくなったこと プロジェクション   追加された。 データバインディング ○ 型が整理された。 (例えば DataServiceCollection) 行数カウント ○ バグフィックス。API 自体は CTP1 と同じ。 フィードカスタマイズ ○ 属性の名前が変更された。 より柔軟になった。 サーバードリブン ページング ○ .NET と Silverlight 3 用のクライアントライブラリが追加された。 BLOB サポート拡張 ○ .NET と Silverlight 3 用のクライアントライブラリが追加された(サーバー側は CTP1 からサポートされていた)。 リクエストパイプライン   追加された。 プロバイダ インターフェース ○ API がリファクタリングされた。

ADO.NET Data Services v1.5 CTP2

ADO.NET Data Services v1.5 の CTP2 が公開された。 ADO.NET Data Services v1.5 CTP2 – Now Available for Download マイクロソフトダウンロードセンターから ダウンロードできる 。CTP2 は CTP1 の機能のアップデートの他、新機能と数多くのバグフィックスが含まれている。以下は、CTP2 に含まれる機能についての説明をおおまかに訳したもの。 プロジェクション : プロジェクションを表現するために URI フォーマットが拡張されました。CTP2 にはサーバー、クライアント両方のライブラリでプロジェクションがサポートされます(LINQ のサポートも含みます)。この機能については今後の投稿で詳細を説明しようと思っています。 データバインディング : データサービスクライアントライブラリが拡張され、WPF や Silverlight ベースのアプリケーションで Two-Way バインディングが可能になりました。 行数カウント : ADO.NET Data Services V1 リリース後、クライアントに全エンティティを持ってくることなしにエンティティ数を取得したいというフィードバックが数多く寄せられました。このニーズに応えるために、全エンティティをダウンロードせずにこの種の情報を取得できるよう、データサービスアドレス方式を拡張しました。 フィードのカスタマイズ(いわゆる Web フレンドリーフィード) : エンティティが AtomPub の各種要素にどうマッピングするかをカスタマイズする機能の提供について多くの質問を受けていました。この機能は、エンティティのプロパティとフィードの要素をデータサービスランタイムがどうやってマッピングするかを、データサービスの作成者が宣言的にコントロールできるようにするものです。 サーバードリブンページング (SDP) : この機能は、各リクエストに対して返すエンティティの総数を制限するものです。さらに、サーバーはクライアントに「next link」、つまり次のエンティティを取得するためのシンプルなURIも提供します。 BLOBサポートの拡張 : ADO.NET Data S

WPF の RichTextBox でキャレットがあるパラグラフを強調表示する

Image
入力補助の一環として、現在編集中の(つまりキャレットがある)パラグラフがわかりやすいように強調表示する方法を考えた。 まずは XAML 定義。ここで大事なのは RichTextBox の SelectionChanged イベントだ。名前からすると、テキストを選択状態にした時に発生しそうなイベントなのだが、実はキャレット移動時に発生する。この SelectionChanged イベントのハンドラで強調表示の切り替えを実装する。なお、Style と Resource の定義は、それぞれデフォルトの文字スタイルと、強調表示用の文字スタイルの定義である。 <RichTextBox Name="richTextBox" SelectionChanged="Highlight"> <RichTextBox.Style> <Style TargetType="RichTextBox"> <Setter Property="FontFamily" Value="MS UI Gothic"/> <Setter Property="FontSize" Value="12"/> </Style> </RichTextBox.Style> <RichTextBox.Resources> <Style x:Key="selectedBlock" TargetType="Block"> <Setter Property="Background" Value="LightBlue"/> <Setter Property="FontSize" Value="16"/> </Style> </Ric