Widows Phone 7でアプリケーション名やバージョン番号をバインドする方法
- 2011-03-28
アプリケーション名の表示や、about画面に表示したいであろうバージョン番号、どうします?直書きのstringやリソースから?それもいいのですけれど、せっかくプロジェクトのプロパティ(AssemblyInfo.cs)で、アプリケーション名やバージョン番号を設定しているわけだから、そこから利用できたほうがいいですよね。
というわけで、これらの情報はアセンブリから取得しましょう。
public class AssemblyInfoData
{
public static readonly AssemblyInfoData ExecutingAssembly = new AssemblyInfoData(Assembly.GetExecutingAssembly());
public string FileName { get; private set; }
public string Version { get; private set; }
public string FileVersion { get; private set; }
public string Title { get; private set; }
public string Description { get; private set; }
public string Configuration { get; private set; }
public string Company { get; private set; }
public string Product { get; private set; }
public string Copyright { get; private set; }
public string Trademark { get; private set; }
public string Culture { get; private set; }
public AssemblyInfoData(Assembly assembly)
{
var assemblyName = new AssemblyName(assembly.FullName);
FileName = assemblyName.Name;
Version = assemblyName.Version.ToString();
FileVersion = GetAttributeName<AssemblyFileVersionAttribute>(assembly, a => a.Version);
Title = GetAttributeName<AssemblyTitleAttribute>(assembly, a => a.Title);
Description = GetAttributeName<AssemblyDescriptionAttribute>(assembly, a => a.Description);
Configuration = GetAttributeName<AssemblyConfigurationAttribute>(assembly, a => a.Configuration);
Company = GetAttributeName<AssemblyCompanyAttribute>(assembly, a => a.Company);
Product = GetAttributeName<AssemblyProductAttribute>(assembly, a => a.Product);
Copyright = GetAttributeName<AssemblyCopyrightAttribute>(assembly, a => a.Copyright);
Trademark = GetAttributeName<AssemblyTrademarkAttribute>(assembly, a => a.Trademark);
Culture = GetAttributeName<AssemblyCultureAttribute>(assembly, a => a.Culture);
}
private string GetAttributeName<T>(Assembly assembly, Func<T, string> selector) where T : Attribute
{
var attr = assembly.GetCustomAttributes(typeof(T), true).Cast<T>().FirstOrDefault();
return (attr == null) ? "" : selector(attr);
}
}
FileName, Versionはnew AssemblyNameに渡してから(WPFだとGetNameで直に取れるのですが、Silverlightだとセキュリティ違反で例外が飛ぶためこうする必要がある)、それ以外の値はカスタム属性から取得できます。また、任意のAssemblyの情報をコンストラクタに投げて取得出来るようになっていますが、どうせ必要なのは実行アセンブリの情報だけでしょ?ってことで、public staticなフィールドにExecutingAssemblyのデータを公開するようにしています。なので、コードからは、 AssemblyInfoData.ExecutingAssembly.Version とアクセスするだけで、簡単に取得できます。
でも、コードから欲しいということはほとんどなくて、UIに表示するためだけに欲しいのですよね、こういう情報は。バインディングしましょう!まず、こんなクラスを用意します。
public class AssemblyInfoDataBindingHelper
{
public AssemblyInfoData Value { get { return AssemblyInfoData.ExecutingAssembly; } }
}
何故これが必要かというと、WPFの場合は{x:static}でstatic変数もバインド出来るのですが、Silverlight/WP7ではバインド出来ないためです。いやあ、カッコ悪いですね、{x:static}欲しいですね、まあ、ないものはしょうがない。
次にApp.xamlのApplication.Resourcesの中に
<Application.Resources>
<!-- Applicationのところで xmlns:local="ネームスペース" を宣言しておく-->
<local:AssemblyInfoDataBindingHelper x:Key="AssemblyInfoData"/>
</Application.Resources>
と書いてリソースを登録。準備はこれで完了で、あとはバインドするだけ。
<TextBlock x:Name="ApplicationTitle" Text="{Binding Value.Title, Source={StaticResource AssemblyInfoData}}" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="{Binding Value.Version, Source={StaticResource AssemblyInfoData}}" Style="{StaticResource PhoneTextTitle1Style}" />
と、以上です。これで下のような感じに
表示されました。ApplicationTitleにTitleは分かりますがPageTitleにVersionは丸っきりイミフ。ボタンは、何となく寂しいから置いただけで意味はないです気にしないで。
AssemblyInfoDataクラスのコードは完全に独立して使い回しが効くので、コピペってどうぞご自由にお使いください。煮るなり焼くなり……、パブリックドメインで。
まとめ
といったのは、一応、今製作中のWP7アプリの一部です。順調に制作は遅れまくり。うむむ。今月中といきたかったのだけど、まーだずれ込みそう。その前は二月中のつもりだったのだけど、Chaining Assertionが思いの外引っ張りすぎて手を付けてる余裕がなかった。とにかく、4月中頃までには、マーケットプレイスで公開したいなあ。あとソースコードも公開します(というか既に製作中のがこっそり公開されてます)。Reactive Extensionsの実践例として、ただたんに非同期で使うというだけじゃなく、こういうケースで使える、コードはこうなる。というサンプルとして役立てればいいな、という思いで書いてますので、適当に待っていてください。
人に見せるためのコード、というのを念頭に置きすぎていて、同じ場所のコードの修正ばかり繰り返していてアプリ全体としては一歩も製作が進まないという超鈍足状態に陥ってますが(コード書きの遅さに定評のある私です(キリッ)、でも、書きなおす度に確実によくなっていく実感はあるので、最終的にそこそこ見せれるコードになるのではないかと思っています。少なくとも、部分的には面白い内容になるはずです。