DataGrid, 脱Reflection(四)

PropertyDescriptorクラスを実装したので、後はCustomTypeDescriptorとTypeDescriptionProviderを実装する。
○CustomTypeDescriptor継承クラス
using System;
using System.ComponentModel;
using System.Reflection;

namespace TawamureDays.ComModels {

/// <summary>
/// Description of TwVMTypeDescriptor.
/// </summary>
public class TwVMTypeDescriptor : CustomTypeDescriptor {

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="descriptor">ICustomTypeDescriptorインスタンス</param>
/// <param name="componentType">提供対象となるクラスタイプ</param>
public TwVMTypeDescriptor(ICustomTypeDescriptor descriptor, Type componentType) :
base(descriptor) {

this.ComponentType = componentType;
return;
}

#endregion

#region CustomTypeDescriptor メンバー

/// <summary>
/// オブジェクトのプロパティ記述子のコレクションを返します。
/// </summary>
/// <returns>プロパティ記述子のコレクション</returns>
public override PropertyDescriptorCollection GetProperties() {
return this.GetProperties(null);
}

/// <summary>
/// オブジェクトのプロパティ記述子のコレクションを返します。
/// </summary>
/// <param name="attributes">フィルターとして使用される属性の配列</param>
/// <returns>プロパティ記述子のコレクション</returns>
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) {

var props = new PropertyDescriptorCollection(null);

//リフレクションを使って、プロパティリストを取得します。
foreach (var propInfo in this.ComponentType.GetProperties(
BindingFlags.Public | BindingFlags.Instance)) {
//プロパティ記述子をリストに加えていきます。
props.Add(new TwVMPropertyDescriptor(propInfo));
}

return props;
}

#endregion

#region 内部プロパティ

/// <summary>
/// 提供対象となるクラスタイプを取得/設定します。
/// </summary>
private Type ComponentType {
get; set;
}

#endregion
}
}

○CustomTypeDescriptor継承クラス
using System;
using System.ComponentModel;

namespace TawamureDays.ComModels {

/// <summary>
/// Description of TwVMTypeDescriptionProvider.
/// </summary>
public class TwVMTypeDescriptionProvider : TypeDescriptionProvider {

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
public TwVMTypeDescriptionProvider() {
}

#endregion

#region TypeDescriptionProvider メンバー

/// <summary>
/// 指定された型およびオブジェクトのカスタムの型記述子を取得します。
/// </summary>
/// <param name="objectType">型記述子の取得対象となるオブジェクトの型。</param>
/// <param name="instance">型のインスタンス。TypeDescriptor にインスタンスが渡されなかった場合、nullでも構いません</param>
/// <returns>型のメタデータを提供できる ICustomTypeDescriptor</returns>
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) {
//用意したTypeDescriptorを使います。
return new TwVMTypeDescriptor(
base.GetTypeDescriptor(objectType, instance), objectType);
}

#endregion
}
}

○使い方
using Systems;
using TawamureDays.ComModels;

namespace TawamureDays {

/// <summary>
/// お試しクラス
/// </summary>
[System.ComponentModel.TypeDescriptionProvider(typeof(TwVMTypeDescriptionProvider))]
public class DataObject : BaseViewModel; {

/// <summary>データ</summary>
public decimal? data_;

/// <summary>
/// データを取得又は設定します。
/// </summary>
public decimal? Data {
get {return data_;}
set {
if (data_ != value) {
data_ = value;
this.RaisePropertyChanged(() => Data);
}
}
}
}
}

自分で使おうと思ったら、意外に回りくどい&めんどくさい。

//...
var dataObj = new DataObject {Data = decimal.One};

//TypeProvidorを取得します。
var providor = TypeDescriptor.GetProvider(typeof(DataObject));
//TypeDescriptorを取得します。
var descriptor = providor.GetTypeDescriptor(typeof(DataObject));

//Dataプロパティ記述子を検索します。
var properties = descriptor.GetProperties();
var prop = properties.Find("Data", false);

//値を取得します。
var val = prop.GetValue(dataObj);
//値を設定します。
prop.SetValue(dataObj, 123M);

TwVMTypeDescriptorクラスのGetPropertiesメソッド内で、リフレクションを使っているので、何度も実行しないようにキャッシュしておくと更に速くなるだろうか。
ただ、実際にDataGridに表示した時、速くなる実感があるかどうか微妙なところだった。
というか、UI仮想化していない状態だと、これを使っても遅かった。まあでも、リフレクションが減っていると思えば、目的を達成できた事にはなるかなぁ。
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m