Home > C# > 目的別資料 > 地域設定

カスタム・マークアップ拡張機能は、どのように動作するか

WPFのための地域設定の手引き Localization Guidance for WPF

原文

WPF Localization Guidance 「Rick StrahlとMichele Leroux Bustamante(2009年6月)」の和訳です。
地域設定の実装の参考にしてください。

関連ファイル

カスタム・マークアップ拡張機能は、どのように動作するか

How the Custom Markup Extension Works

ResExtensionの実装は、簡単です。それは、背後で、直接リソースを取得する、1つ以上のResourceManagerインスタンスを使用します。 そして、それらに、マークアップ拡張機能の構文を使用する結合によって、XAMLドキュメントを提供します。 一旦、リソース値を取得した型であれば、変換は、文字列の値を、プロパティ型を取得したマークアップ拡張機能が結合している値に、一致させるために適用されます。 マークアップ拡張機能の前提は、すべての値が文字列値であるということです。利用できる場合、それは、結合したプロパティの値コンバータによって送られます。 全体の処理は、エラー処理ブロックによりラップされます。それは、どんな結合のエラーでも捕えて、Default値の表示に戻します。 エラーが発生する場合、また、エラーは、Trace出力に書き込まれます。 それをデバッグモードで実行するとき、あなたは、Output Windowを使用して、Visual Studioでモニターすることができます。

FIGURE 21:

ResExtensionカスタム拡張機能は、リソースを取得するために、直接、ResourceManagerインスタンスを使用します。 そして、XAMLドキュメントにそれらを供給します。

FIGURE 21

ここにある、マークアップ拡張機能の全体を説明するのは、この記事の範囲を越えています。 しかし、あなたに、マークアップ拡張機能に必要な考えを与えます。 そして、ResExtensionが、Figure 22で与える値で、どのように動作するかは、ProvideValueInternal関数(簡略化された)に示します。 それは、ほとんどの操作を処理します。

FIGURE 22:

ResExtensionマークアップ拡張機能の、重要なProvideInternalメソッドは、リソースの検索、書式設定と必要に応じてエラー処理を処理する中心的なメソッドです。


private object ProvideValueInternal() 
{ 
	object localized = null; 
	if (Static == null) 
	{ 
		// Get a new or cached resource manager for this resource set 
		// このリソース・セットのための、新しい、あるいは、
		// キャッシュに格納されたリソースマネージャを手に入れます。
		ResourceManager resMan = this.GetResourceManager(this.ResourceSet);

		// Get the localized value
		// 地域設定された値を手に入れます。
		if (resMan != null) 
			localized = resMan.GetObject(this.Id); 
} 
else 
{ 
	try 
	{ 
		// Parse Static=properties:Resources.HelloWorld 
		int index = this.Static.IndexOf('.'); 
		if (index == -1)
		throw new ArgumentException(); 

	// resolve properties:Resources
	//プロパティ:Resourcesを解決します
	string typeName = this.Static.Substring(0, index); 
	IXamlTypeResolver service = 
		_serviceProvider.GetService(typeof(IXamlTypeResolver)) 
		as IXamlTypeResolver; 
	Type memberType = service.Resolve(typeName); 

	string propName = this.Static.Substring(index + 1); 
	localized = memberType.GetProperty(propName, 
		BindingFlags.Public | BindingFlags.Static | 
		BindingFlags.FlattenHierarchy) 
		.GetValue(memberType, null); 
	} 
	catch 
	{ /* ignore retrieval errors */ }
	{/*検索エラーを無視します*/}
}

// If the value is null, use the Default value if available
// 値がnullの場合、もし、利用できれば、Default値を使用します。
if (localized == null && this.Default != null) 
	localized = this.Default; 

// fail type conversions silently and write to trace output
// 型変換は静に失敗し、トレース出力に書き込まれます
try
{
		// Convert if a type converter is availalbe 
		// 型コンバータが利用できる場合、変換します
		if (localized != null && 
			this.Converter == null && 
			_typeConverter != null && 
			_typeConverter.CanConvertFrom(localized.GetType())) 
			localized = _typeConverter.ConvertFrom(localized); 

		// Apply a type converter if one was specified 
		// 1つが指定された場合、型コンバータを適用します
		if (Converter != null) 
			localized = this.Converter.Convert(localized, 
			_targetProperty.PropertyType, 
			null, CultureInfo.CurrentCulture); 
} 
catch (Exception ex) 
{ 
	Trace.WriteLine(string.Format( Resources.ConversionErrorMessageFormatString, 
			Id, ex.Message)); 
			localized = null; 
} 

// If no fallback value is available, return the key 
// 代替システムの値が利用できるない場合、キーを返します
if (localized == null) 
{ 
if (_targetProperty != null && 
_targetProperty.PropertyType == typeof(string)) 
localized = string.Concat("?", Id, "?"); 
else 
return DependencyProperty.UnsetValue; 
} 

// Format if a format string was provided
// 書式設定文字列が与えられた場合、書式を設定します
if (this.Format != null) 
	localized = string.Format(CultureInfo.CurrentUICulture, 
			this.Format, localized); 
	return localized; 
}
			

マークアップ拡張機能は、それらを結合するために、コントロールとプロパティに関する情報を受け取ります。 それは、結合されたコントロール・オブジェクト・インスタンスと依存関係プロパティを与えます。 また、依存関係プロパティに基づいて、あなたは、型コンバータを取得することができます。 それは、文字列から適切なプロパティ型に、値を変換できます。 これらの参照は、ResourceManagerから取得される文字列に基づいて、値を設定するために使用することができます。

マークアップ拡張機能は、先程、説明した、プロパティを持っています。(ID、ResourceSet、Defaultなど) そして、これらのプロパティに基づいて、コードは、適切なResourceManagerとリソースIDを取得することを試みます。 一旦、値が取得されると、型コンバータは、適切に、その書式の設定を適用することができます。 エラーの発生、あるいは、リソースIDの検索が失敗した場合、一般的に、指定した場合、既定の値を指定することによって、戻り値を修復できます。

マークアップ拡張機能の実装は、あなたが、比較的簡単に達成することができる実用的な例ですが、単純です。 この仕組みには、多くの機能があります。そして、見ての通り、ユーザー定義した動作の作成は、非常に簡単です。

このマークアップ拡張機能の動作の例については、WpfLocalizationResxプロジェクトとLocalizationInfo.xamlドキュメントを見てください。 それは、地域設定のために、StaticExtensionとResExtensionの両方を使用します。

ユーザー定義したマークアップ拡張機能の利点と欠点は、静的な結合といくつかの類似点を持っています。 あなたは、更に、結合式を処理しています。そして、このように、あなたは、依存関係プロパティに結合することだけができます。 更に、あなたが、また、静的な結合とマークアップ拡張機能を組合せて使用できることに注意して下さい。 あなたが、常に、Resx文字列リソースと結合している場合、続いて、あなたが、文字列ではない値に結合する必要があるとき、 あなたはマークアップ拡張機能を使用することができ、x:Staticを使用することは、 多くの場合、最も簡単であり、そして、最も効果的な選択子を除外します。

Resxリソースのどちらの結合方法でも、あなたに最大限の柔軟性とコントロールとプロパティへのマッピング・リソースの最初の処理がより複雑な、 結合処理の制御を提供します。

StaticExtensionと比較した、ユーザー定義したマークアップ拡張機能の長所は以下のとおりです。:

静的な結合より柔軟性がある

厳格に型指定されたリソースか、未加工のResourceManagerのどちらかを使用します。

あなたは、厳密に型指定された静的なリソースへの結合を選択することができます。 あるいは、ユーザー定義したResourceManagerインスタンスを使用して、あなたのマークアップ拡張機能が、インスタンスを生成します。

TypeConverterのサポートは、複雑な型の文字列表現を可能にします。

ユーザー定義したマークアップ拡張機能の型コンバータを、内部的に適用することによって、保証することができます。 それは、あなたが、同じ文字列の値を使用して、簡単に、文字列ではないプロパティに結合することができます。 あなたは、XAMLマークアップの属性の中で、すでに使用しています。

ユーザー定義したResourceManagerやリソースの記憶ができます。

あなたに、あなたが、ユーザー定義したResourceManagerを使用したり、さらに、直接、XMLやデータベースからリソースを読み込んで、 完全に、ResourceManagerを迂回する完全な別々のリソースの記憶を作成することができるので、 マークアップ拡張機能は、リソースがどのように読み込まれるかについて、完全な自由を与えます。

デザイナーでの、リソースの読込失敗のための対応

リソースの読込失敗は、設計時の経験と同じように、実行時に、アプリケーションを壊すことができます。 これは、多くの場合、リソースが、Visual StudioとBlendデザイナーによって見つからない、サテライト・アセンブリの状況で、特に当てはまります。 たとえ、リソースが直接アクセス可能でないとしても、既定の値は、デザイナーが、常に動作することを確実にするために役に立ちます。

その場でカルチャを変更する

マークアップ拡張機能は、それらが、結合している対象の更新を強制する機能をサポートしています。 それで、あなたが、カルチャの変更を検出することができる場合、値を更新することができます。 それがドキュメントを再ロードすることなく、結合されます。この話題は、この白書の後の方で説明します。

短所は以下の通りです。:

カスタム設定が必要

ユーザー定義したマークアップ拡張機能の名前空間は、すべてのページに登録する必要があります。 そして、おそらく、LocalizationSettings.Initialize()に類似したアプリケーションの起動で、いくつかのグローバル構成を必要とします。

Blendデザイナーの問題

厳格なセキュリティー環境そして、Blendが、リソース・アセンブリを解決する方法のために、Blendデザイナーで表示される、ライブリソースを見るのは問題があります。 既定の値は、この問題を軽減することができ、そして、Blendにおいて、設定する場合、あなたは既定の値を見ることができます。

標準的でない解決法

本来、ユーザー定義した拡張機能は、組込みの解決法でありません。 これは、ローカライザが、外部アセンブリをインストールする必要があることを表しています。そして、マークアップ拡張機能を使用するために、ユーザー定義した構文を使用する必要があります。

このエントリーをはてなブックマークに追加

Home PC C# Illustration

Copyright (C) 2011 Horio Kazuhiko(kukekko) All Rights Reserved.
kukekko@gmail.com
ご連絡の際は、お問い合わせページのURLの明記をお願いします。
「掲載内容は私自身の見解であり、所属する組織を代表するものではありません。」