C#Programing Archive

JAN
2

あけましておめでとうございます。今年もよろしくお願いします。

新年の抱負を語る前に、去年のことを振り返ってみると、去年の初めも、「今年こそはBlogでしっかりアウトプットを出していく!」と考えていたのですが、結局またアウトプットを出せなかった一年となってしまいました。でも!今年こそは!今年こそは!書きます!・・・と宣言するだけでは去年から進歩がないので、Blogを書くネタにできるようなソフトウェアを今書いています。今春から働き始める会社が、IPネットワーク関係の会社なので、その辺の流行のトピックと絡めたソフトウェアをC#で書くことで、ネットワーク技術の流行とモダンなC#のコーディングスタイルのキャッチアップを図りつつ、Blogのネタにしていきたいと考えています。働き始めると慣れるまで時間がとりにくくなるかと思うので、とりあえず4月までを目途に、リリースしたいなと考えています。頑張ります。

忙しくてとりあえず登録したものの放置していたApp Hubからメールが来ていました。Winodws Phone Marketplaceのアップデートに伴い、学生の身分証明プロセスが簡素化されたみたいです。折角だし端末unlockしてMango Beta化してみようかな。

Important Enhancement to App Hub Registration Process for Students

July 22, 2011

Now that the next release of the Windows Phone Marketplace App Hub has launched, we are reaching out to make you aware of a change to the registration process and how it may impact your account.

In the new release of App Hub, publisher identification for Student accounts happens in real-time during account registration. You no longer have to submit an application to trigger a separate publisher identity verification process.

Since you have not yet submitted an application, the next time you sign in to App Hub, you will notice your account will be reverted back to Step 1 of the registration process. All of the information you have previously provided will be pre-populated and you will be asked to follow the onscreen instructions to complete your account activation.

Once you’ve completed registration your account will be immediately activated and you can unlock your phone for in-device testing. This will greatly simplify the process of getting your account activated and, ultimately, your apps published to the Windows Phone Marketplace.

If you have any questions or concerns, please contact
mailto:apphub@microsoft.com
apphub@microsoft.com  
and we will be happy to assist you.

Best regards,

The Windows Phone Marketplace Team

Microsoft respects your privacy. Please read our online
http://privacy.microsoft.com/en-us/default.mspx
Privacy Statement .

Microsoft Corporation

One Microsoft Way

Redmond, WA 98052 USA

MAY
5

厳しいかも。

Silverlight 4で追加されたTrusted mode、とりあえず試してみているのだけど、結構制限が厳しくてつらい感じ。。Cookieは使えないし、GETメソッド使っているときに、headerを追加することもできない。これは、SilverlightがHTTP通信のスタックに、OSのTCP/IPスタックを直接たたいているのではなく、ブラウザのPlugin APIを叩いているためだとか。

Silverlight only supports setting headers using the POST method not the GET method. This is due to a limitation in how the TCP/IP stack is implemented in Silverlight. It uses the browser extension APIs instead of going directly against the host OS’s APIs.
http://stackoverflow.com/questions/622897/how-can-i-set-headers-with-silverlight-get-httpwebrequest

この問題を回避する方法としては、@jz5さん曰く、Socketを自分で叩いてHTTP通信すればいい、ということらしい。なんだかなぁ。。Silverlight 4でTrusted Modeをどれぐらい使う需要があるかは知らないけど(自分ならWPF+ClickOnceでいいや)、Windows PhoneアプリをSilverlightで書こうか、という場合に結構辛い気が。。WindowsPhoneは微妙に普通のSilverlightとビルディングブロックが違ってるから、案外動くのかもしれないけど(希望的観測)。

(追記) 試しにWindows Phoneでやってみたらheader追加できたw 嬉しいんだけど、HttpWebRequestみたいな非常に一般的なクラスでこのように挙動が違うというのは、困るので、正直複雑。何とかならんのか。

昨日開催された、 プログラミング生放送勉強会 第2回 @新宿に行ってきました。ニコニコ生放送のプログラミング関係のオフ会ということなのですが、自分はそれまでニコニコ生放送というものを見たことがなかったので、若干どんなノリの会なのか分からずに行ったのですが、まぁ、わんくま勉強会と似たようなノリで、楽しんで帰ることができました。やはり、動画でセッションの模様を中継でき、それに対する反応がネットの向こう側で観ている側から帰ってくるというインタラクションは大変面白いですね。ただ、帰ってくる反応も、ニコニコ動画のカルチャーに影響されているところがあり、もっとフォーマルなイベントで公式に使うのは難しいだろうなということも身をもって感じました。

さて肝心の内容。色々面白い話が多かったですが、.NET好きという自分の性格も手伝って、Live Labs Pivotの紹介話とXBox LIVE インディーズゲーム製作苦労話、Gainer紹介といくつかのLTが特に面白かったです。

Live Labs Pivotは、事前に名前しか知らずに行ったのですが、あれはある形式に則ったデータを食わせたら、それをSeaDragonテクノロジ他を使って綺麗に整理して見せるデモアプリケーションというイメージで良いんでしょうか。インビテーションを取得するのが手間そうなので実際に使ったわけでないのですが、デモを見る限りWPFで実装されているのかな?いつかLive wave xでWindows LiveやBingのオプション機能として、このようなインターフェイスがSiverlightを使って実装されて欲しいものです。

XBox LIVE インディーズゲームの話は、XBox LIVE インディーズゲームを実際に製作されている方が、製作にあたっての技術的でない苦労点を語ったセッションでした。やっぱり、家庭用ゲームコンソールで動くゲームを作って販売できるというのは大変魅力的な話のようですが、それに見合った苦労もされていうようで、iPhoneアプリ同様アメリカへの税金払い方の話だとか、表現の規制に関する話だとか、インターフェイスに使う言語の話だとか。表現の規制の話は、まぁ家庭用ゲーム機なら控えめにならざるを得ないというのはよくわかる話だったのですが、ゲームのインターフェイスに使われる言語に、日本向けのゲームにアルファベットが使われているだけで外国人からピアレビューで差し戻しを受けて直さざるを得なかったというのは、どう考えても運営方針が間違っているような。。まだ始まったばかりの仕組みなので運営側も試行錯誤している段階なのでしょうが、聞いている限りだと、製作者と運営側のコミュニケーションロスによる問題のような気も。やっぱり海外で作られているスキームを使う場合には、こちらも交渉できるだけの英語力が求められるのだなぁと勝手に納得してました。

Gainer。イケメンのための雑誌の方じゃないよ、電子工作の方だよ、というギャグほか、スピーカーの方のしゃべりの上手さに大いに笑わせてもらったセッションでした。Gainer、面白そうですね。なんちゃって理系ですらないSFCでぼんやり過ごしていると、電子工作方面への知識が全く欠けているのですが、Gainerは自分みたいな高級言語ばっかり触っている人間が電子工作始めるのに最適なおもちゃだということがよく分かりました。PCの中に立てたローカルなサーバーを叩いてやるだけでいいというのは非常に手軽ですね。。近いうちに買いたいと思います。

P1020471そいういえば場所はMicrosoftの新宿オフィスのセッションルームの一室だったのですが、新宿のサザンテラス口側は結構イルミネーションが綺麗なんですね。向かいの高島屋や紀伊国屋側も綺麗ですし。

OCT
10

E30HT

Published:2009-10-10 01:36:35 UTC

研究室にAU初のスマートフォン、E30HTが届きました。いわゆるTouch Pro。なんかのプロジェクトで使う端末らしいです。折角なので姉妹機である自分のTouch Diamondと並べてみました。

091005_1502~01 091005_1508~01

Touch Proのキーボードがある側だけでTouch Diamondと同じ厚みがある。。まぁ、Touch Diamondが薄くて良い端末だと信じることにします(ぇ

以前あげたC# .NETアプリケーション開発 徹底攻略 Listing2.26への疑問 – SharpLab.というエントリに対して、なちゃさんから、

なちゃ 09-09-23 09:15:19 JST

本来、デリゲートでBeginInvokeした場合は、必ずEndInvokeする必要がありますね。
リソースリークなども発生する危険があります。
※デリゲート以外でもBegin~系は基本的には同じですが

EndInvokeさえすれば、きちんと発生した例外がスローされてきます。
けして例外が握りつぶされているのではなく、正しく使っていないために握りつぶされているように見えているだけですね。
ちょっと書籍の記述がまずいと思います。

という指摘がありました。なるほど!指摘の通り、Begin EndパターンなのでEndInvokeを必ず呼び出す必要がありました。恥ずかしながらすっかり失念していました。。というわけでEndInvokeを使うように修正。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace SharpLab.ThreadExceptionTest {
	static class Program {

		static Form form;

		/// <summary>
		/// アプリケーションのメイン エントリ ポイントです。
		/// </summary>
		[STAThread]
		static void Main() {

			Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
			Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(Program_UnhandledException);

			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);
			form = new Form();
			Application.Run(new Form1());
		}

		static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) {
			MessageBox.Show(e.Exception.Message);
		}

		static void Program_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
			Exception ex = (Exception)e.ExceptionObject;
			MessageBox.Show(ex.Message);
			Application.Exit();
			Environment.Exit(0);
		}

	}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace SharpLab.ThreadExceptionTest {
	public partial class Form1 : Form {
		public Form1() {
			InitializeComponent();
		}

		private delegate void SampleDelegate();

		private void button1_Click(object sender, EventArgs e) {

			SampleDelegate a = new SampleDelegate(ThreadMethod);
			a.BeginInvoke((asyncResult) => {
				a.EndInvoke(asyncResult);
			}, null);
		}

		private void ThreadMethod() {
			//意図的に起こした例外
			Thread.Sleep(5000);
			throw new Exception("非同期スレッドで起こった例外です。");
		}

	}
}

image

こんな感じでしょうか。ちゃんとサブスレッドで例外が発生した時にUnhandledExceptionが呼び出されるようになりました!これで正しく確実な終了処理ができそうです。サブスレッドの処理内容をすべてtry~catchで括って必要に応じて例外をリスローする必要があると憶えていたのですが、そうではなかったのですね。いつもtry~catch書きながらなんかおかしい気がしていたのですが、これですっきりしました。なちゃさん、ありがとうございました。

前のエントリで紹介したWebkit.NETはまだC#などのコードからDOMにアクセスする方法は実装中であるため、正式には提供されていません。提供されているのは基本的なナビゲーションなどに限られています。そのため、出来ることは相当制限されています。がしかし、表示されているページの中でJavaScriptのコードを実行させる方法がForumに上がっていましたので紹介します。これがあれば多少の助けにはなりそうです。

ソースコードはこんな感じ。

private void button1_Click(object sender, EventArgs e) {
    FieldInfo fi = typeof(WebKitBrowser).GetField("webView", BindingFlags.NonPublic| BindingFlags.Instance);
    WebView webView = (WebView)fi.GetValue(this.webBrowser1);
    webView.stringByEvaluatingJavaScriptFromString(@"document.body.innerHTML = 'Hello Webkit DOM!';");
}

リフレクションを使っています。WebKitBrowserにはwebViewというprivateなメンバがあり、それはWebViewインターフェイスを実装しています。このwebViewをリフレクションで取得し、そのメンバにstringByEvaluatingJavaScriptFromStringというJavaScriptコードを引数として渡してやると実行してくれるメソッドがあるので、これを利用するという方法です。このメソッドの戻り値の型はstringなのですが、実行結果を取得することはどうもできないようです。 WebViewの他のメンバの実装がどれぐらい進んでいるかはまだ試していないのでわからないのですが、WebViewについては、Webkitですし、Cocoaのリファレンスを参照するとよさそうな感じがします。

SEP
18

Webkit.NETを触ってみた

Published:2009-09-18 01:52:13 UTC

image 「C#凄い使いやすくて良い言語なんだけど、WebBrowserコントロールは残念だよなー、Trident最近頑張ってるんだけどWebkitとかに比べるとまだまだだよなー」とか常日頃から感じていたのですが、ふと「WebkitをC#から扱うためのラッパーとか探せばあるんじゃね?」という思いつきで「Webkit .net」とググってみると、ありましたありました、「Webkit.NET」というまんまなタイトルのプロジェクトが。オープンソース恐るべし。コンパイル済みのバイナリと共に、サンプルアプリがあったので実行してみました。

image

・・・なにこれ凄い。日本語も全く普通に通りますし、普通に使えそうです。というわけで自分でもテスト用にWinFormsプロジェクトを作って動かすテストをしてみたので、メモを残しておきます。

まず、WebKit.NETライブラリをWebKit .NET | Get WebKit .NET at SourceForge.netからDLしてきます。その中のbinフォルダ内のファイルがライブラリを構成しています。WebKitBrowser.dllがC#から参照するラッパーです。

まず、WebKitBrowserをツールボックスに追加してやります。ツールボックスのコンテキストメニューの「アイテムの選択」という項目をクリックします。

image

この際、ダイアログが表示されるまで、めちゃ重たいかもしれませんが、ぐっとこらえましょう。

image

そして参照ボタンをクリックして、WebKitBrowser.dllを選択してやれば、ツールボックスにWebKitBrowserが追加されます。

image

あとは普通にコントロールをポトベタしておわり…でもありません。。

まず、プロジェクトのプロパティから、プラットフォームターゲットをx86に設定します。Webkitは、現在、x86版のみ提供されているそうです。
image

続いて、デバッグのタブにある、「Visual Studio ホスティング プロセスを有効にする」という項目のチェックを外します。Visual Studioホスティングプロセスは、Visual Studioでのデバッグを効率化させるためのもののようですが、今回のようにアンマネージドコードを連携する場合は上手く働かず、エラーの原因になることがあるようです(Visual Studioホスティングプロセスの解説:VSホスト・プロセス(*.vshost.exe)とは何か?[VS 2005のみ、C#、VB] - @IT)。これが原因のエラーにぶつかって、@JZ5さんに助けを求めたところ、このオプションを教えていただけました。ありがとうございました。

image

こうしてビルドした上で、最後に仕上げに、ビルドして出来た実行ファイルやWebKitBrowser.dllと同じディレクトリに、Webkit本体であるWebkit.dllや、その依存するdll群を放り込みます。ビルド後のイベントでコピーするコマンドを発行してやると良いようです。

image

というわけで出来ました。よいよい。素晴らしい。DOM周りのメンバの実装が未だらしく、出来ることは結構限定されていますが、Monoでも動かせるようにしたいよねー、とREADMEに書かれていたりと、これからの進展に期待したいプロジェクトです。

CardSafe/EはMVVMパターンに則って作るように心掛けたのですが、WPFと同じ感覚でSilverlightにMVVMパターンを適用しようとすると、色々と不都合が出てきて苦労させられました。Silverlightではオミットされている機能が結構あるので、そこに引っかかるとしばしば手戻りが発生します。このエントリではCardSafe/Eを書いていて気付いた点をとりあえず二点ほど。

SilverlightにはDataTemplate.Datatypeが存在しない

地味に痛いですこの仕様。ItemsControlから派生したコントロール(ListBoxなど)のItemをItemsSourceにセットしたINotifyPoropertyChangedを実装したコレクションから生成する際に、コレクションが列挙するインスタンスの型によってDataTemplateを切り替える場合、WPFではDataTemplate.Datatypeがあるので重宝するのですが、Silverlightでは3 RTWでもサポートされていません。DataTemplateSelectorもサポートされていないので、インスタンスの型や状態によってDataTemplateを切り替えることはできないようです。とりあえず逃げ道として自分はDataContextにセットされたインスタンスをみてContentを書き換えるロジックを書いたUserControlを用意しているのですが、面倒ですね。XAMLで宣言的に書きたいのでDataTemplate.Datatypeは是非サポートしてもらいたいものです。

TabcotrolのItemsSourceはTabItemのコレクションしか受け付けない

なんでー!?これまたあんまりな仕様。WPFではItemsControlから派生したコントロールのItemsSourceにINotifyPoropertyChangedを実装したコレクションをセットすると、その列挙する内容をListBoxItemやTabItemなど適当なコンテナに包んで表示してくれるので、あとはDataTemplateで表示内容を好きなようにカスタマイズしてやればよかったのですが、SilverlightのTabControlのItemsSourceはTabItemのコレクションしか受けてつけてくれないという。。これではTabItemに対応するViewModelのインスタンスをセットし、DataTemplateでViewを設定して表示内容をカスタマイズするというM-V-VMでよく知られたパターンが使えません。SilverlightでもListBoxではListBoxItem以外も受け付けてくれたのですけどねぇ。。ではどうするか。自分の場合はViewModelのコレクションをラップしてTabItemのコレクションとして公開するラッパークラスとConverterを用意することで凌ぎました。

ラッパークラスはこんな感じです。ViewModelのコレクションとViewModelからTabItemへの変換を行うFuncをコンストラクタの引数として取ります。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Controls;

namespace SharpLab.CredentialsLockerSilverlight.ViewModels {
	public class ReadOnlyObservableTabItemCollection<TViewModel, TViewModelCollection> : ICollection<TabItem>, INotifyCollectionChanged where TViewModelCollection : ICollection<TViewModel>, INotifyCollectionChanged {

		private TViewModelCollection _viewModels;
		private ObservableCollection<TabItem> _tabItems;
		private Func<TViewModel, TabItem> _converter;

		public ReadOnlyObservableTabItemCollection(TViewModelCollection viewModels, Func<TViewModel, TabItem> converter) {
			_converter = converter;
			_viewModels = viewModels;
			_tabItems = new ObservableCollection<TabItem>();

			foreach (var item in _viewModels) {
				_tabItems.Add(_converter(item));
			}

			_viewModels.CollectionChanged += new NotifyCollectionChangedEventHandler(_viewModels_CollectionChanged);

			_tabItems.CollectionChanged += new NotifyCollectionChangedEventHandler(_tabItems_CollectionChanged);
		}

		void _viewModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
			switch (e.Action) {
				case NotifyCollectionChangedAction.Add:
					_tabItems.Insert(e.NewStartingIndex, _converter((TViewModel)e.NewItems[0]));
					break;
				case NotifyCollectionChangedAction.Remove:
					_tabItems.RemoveAt(e.OldStartingIndex);
					break;
				case NotifyCollectionChangedAction.Replace:
					_tabItems.RemoveAt(e.OldStartingIndex);
					_tabItems.Insert(e.NewStartingIndex, _converter((TViewModel)e.NewItems[0]));
					break;
				case NotifyCollectionChangedAction.Reset:
					_tabItems.Clear();
					foreach (var item in _viewModels) {
						_tabItems.Add(_converter(item));
					}
					break;
			}
		}

		void _tabItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
			if (CollectionChanged != null) {
				CollectionChanged(this, e);
			}
		}

		public event NotifyCollectionChangedEventHandler CollectionChanged;

		#region ICollection<TabItem> メンバ

		public void Add(TabItem item) {
			throw new NotSupportedException();
		}

		public void Clear() {
			throw new NotSupportedException();
		}

		public bool Contains(TabItem item) {
			throw new NotImplementedException();
		}

		public void CopyTo(TabItem[] array, int arrayIndex) {
			throw new NotSupportedException();
		}

		public int Count {
			get {
				throw new NotImplementedException();
			}
		}

		public bool IsReadOnly {
			get {
				return true;
			}
		}

		public bool Remove(TabItem item) {
			throw new NotSupportedException();
		}

		#endregion

		#region IEnumerable<TabItem> メンバ

		public IEnumerator<TabItem> GetEnumerator() {
			foreach (var item in _tabItems) {
				yield return item;
			}
		}

		#endregion

		#region IEnumerable メンバ

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

		#endregion
	}
}

これを以下のようなConverterから利用します。

using System;
using System.Collections.ObjectModel;
using System.Windows.Controls;
using System.Windows.Data;
using SharpLab.CredentialsLockerSilverlight.ViewModels;

namespace SharpLab.CredentialsLockerSilverlight.Views.Converter {
	public class CardVMCol2TabItemColConverter : IValueConverter{
		#region IValueConverter メンバ

		public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
			return new ReadOnlyObservableTabItemCollection<CardViewModel, ObservableCollection<CardViewModel>>((ObservableCollection<CardViewModel>)value,
				(each) => {
					var newTabItem = new TabItem() {
						DataContext = each,
						Header = new CardTabHeaderView(),
						Content = new SharpLab.CredentialsLockerSilverlight.Views.CardView()
					};
					return newTabItem;

				});
		}

		public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
			throw new NotImplementedException();
		}

		#endregion
	}
}

こうしてやることでTabControlのItemsSourceにViewModelのコレクションをバインドできるようになります。Converterは無理を通すのに便利な機能ですね。。

 ItemsSource="{Binding Path=CardViewModels, Converter={StaticResource CardVMCol2TabItemColConverter}}"
JUL
13

Silverlight 3のRTWがリリースされましたね。Silverlight Tools for Visual Studio 2008やExpression BlendのRCもリリースされています。version3から本気出すというMSの本領発揮とばかりに、結構便利になってきました。このエントリでは、自分が弄ってみて気づいたSilverlight 3 Betaからの変更点を書いてみたいと思います。

Silverlight 3 SDK Betaに含まれていたコントロールの一部がSilverlight Toolkitに移動

DataForm, DockPanel, WrapPanel, Expander, HeaderedContentControl, ViewboxがToolkitに移動したようです。それに伴って所属する名前空間が変わっているので注意が必要です。

Interactivity.dllの名前空間の変更

Expressionでは、3 MixPreviewからBehaviorというパターンがサポートされました。3 MixPreviewではプロジェクトでMicrosoft.Expression.Interactivity.dllというアセンブリを参照した上で、Behavior<T>クラスなどを継承して自分でBehaviorを作成するか、Microsoft Expression Community Galleryなどからダウンロードして使うという流れでした。今回リリースされたExpression 3RCでは、Microsoft.Expression.Interactivity.dllがSystem.Windows.Interactivity.dllと改名され、名前空間も変更されているので注意が必要です。この改名はBlend SDKの絡みでしょうか。また、BehaviorやTriggerActionの組み込み実装として、StoryBoardActionなどがMicrosoft.Expression.Interactions.dll内で提供されていますので、Microsoft Expression Community Galleryと共に活用していくよいでしょう。

DataGridのItemsSourceへのBindingが上手くいかない問題が修正

Silverlight 3 Betaの頃はDataGridのItemsSourceへのBindingが上手く動かないという問題がありました(DataGrid — binding to ItemsSource is broken : The Official Microsoft Silverlight Site)。今は修正されています。(これはむしろSilverlight Toolkitの話?)

Silverlight Tools for VS2008のSilverlightデザイナ削除

Silverlight 3 Tools for VS2008ではSilverlightデザイナが削除されています。まぁプレビューが上手く出来ない場合も多かったので、VS2010に期待ですね。今のうちにBlend 3に習熟しておきたいものです。