3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(.Net)オブジェクトのメンバ情報とメンバの値を動的に取得する

オブジェクト指向だと値を格納する目的のクラスってよく使います。(例えば、社員クラスとか...)

で、それらのデータ格納用クラスのメンバ変数を一気に出力するのを汎用的にするというのが今回の目的です。

例えば下記のようなクラスがあるとします。

public class Person

{

public string FirstName { get; set; }

public string LastName { get; set; }

public DateTime Birthday { get; set; }

public List FamilyNames { get; set; }

}

public class Car

{

public string CarName { get; set; }

public string Engine { get; set; }

public int DryWeight { get; set; }

public int HorsePower { get; set; }

}

汎用的(つまりどのクラスでも使えるよう動的)にするには下記のようにします。(汎用的でない例も入れてます)(C#)

private void button1_Click(object sender, EventArgs e)

{

//テストクラスのインスタンス生成(.Net 3.0以降で使えるクラス初期化の方法)

Person prs = new Person()

{

FirstName = "礼司",

LastName = "安部",

Birthday = new DateTime(1971, 10, 10),

FamilyNames = new List { "安部優", "安部永太","ちび安部" }

};

Car car = new Car() {

CarName = "GT-R",

Engine = "VR38DETT",

DryWeight = 1740,

HorsePower = 480

};

 

Console.WriteLine("--------------汎用的でない出力の仕方--------------");

Console.WriteLine("FirstName 値 : " + prs.FirstName);

Console.WriteLine("LastName 値 : " + prs.LastName);

Console.WriteLine("Birthday 値 : " + prs.Birthday.ToString());

Console.Write("FamilyNames 値 : ");

foreach (string item in prs.FamilyNames)

{

Console.Write(item+",");

}

Console.WriteLine("\n\n--------------汎用的な出力の仕方--------------");

//prsオブジェクトのメンバと値を出力。typeof(型)を忘れずに。

OutputProperty(prs,typeof(Person));

//carオブジェクトのメンバと値を出力

OutputProperty(car, typeof(Car));

 

//prsオブジェクトのListの場合は下記のようにすればよろし

List lstp = new List();

lstp.Add(prs);

lstp.Add(new Person() { FirstName = "aaa", LastName = "bbb", Birthday = new DateTime(1971, 10, 10) });

lstp.Add(new Person() { FirstName = "ccc", LastName = "sss", Birthday = new DateTime(1971, 10, 10) });

Console.WriteLine("\n\n--------------汎用的な出力の仕方(List版)--------------");

//出力。ListをArrayListにすることが肝かな。

OutputPropertyArray(new ArrayList(lstp), typeof(Person));

}

 

///

/// オブジェクトのメンバを取得しプロパティなら表示する。

///

/// クラスのインスタンス

/// クラスのTypeオブジェクト

private void OutputProperty(object targetobj, Type t)

{

//using System.Reflection;が必要

//メンバを取得する

MemberInfo[] members = t.GetMembers(

BindingFlags.Public |

BindingFlags.Instance |

BindingFlags.DeclaredOnly);

 

foreach (MemberInfo m in members)

{

//メンバの型と、名前を表示する

//メンバの型がプロパティなら

if (m.MemberType.ToString().Equals("Property"))

{

Console.WriteLine("メンバ型:{0} - メンバ名:{1}", m.MemberType, m.Name);

PropertyInfo pr = t.GetProperty(m.Name);

object resobj = pr.GetValue(targetobj, null);

//Listならカンマ区切りで表示

if (resobj != null && typeof(List).IsAssignableFrom(resobj.GetType()))

{

List lstRes = (List)resobj;

//LINQを使用してListをカンマ区切りで結合する。(ループで回してもいいんだけどこっちの方がシンプルなんで...)

Console.WriteLine(" 値 : " + string.Join(", ", lstRes.ToArray()) );

}

else if (resobj != null)

{

Console.WriteLine(" 値 : " + resobj.ToString());

}

}

}

}

 

///

/// Listコレクション

///

/// クラスのインスタンスのコレクション

/// クラスのTypeオブジェクト

private void OutputPropertyArray(ArrayList targetobj, Type t)

{

foreach (var item in targetobj)

{

OutputProperty(item, t);

}

}

オブジェクトのメンバの型情報を取得するには、クラスの Type 情報を取得し、GetMembers メソッドで取得できます。

この際、どこまでを含めるかのフラグの指定は、MSDN:BindingFlags 列挙体 (System.Reflection)を使います。

メンバの値の取得は、プロパティの場合 Type.GetProperty("名前") で PropertyInfo オブジェクトを取得し、GetValue メソッドで可能です。

メソッドの場合は MethodInfo 、フィールドの場合は FieldInfo クラスを使えるようですね。

取得したプロパティの値が List かどうかは、(.Net)objectがListかまたは配列かどうか判定する で詳しく書いています。

上記コードを実行した結果は下記のようになります。

--------------汎用的でない出力の仕方--------------

FirstName 値 : 礼司

LastName 値 : 安部

Birthday 値 : 1971/10/10 0:00:00

FamilyNames 値 : 安部優,安部永太,ちび安部,

--------------汎用的な出力の仕方--------------

メンバ型:Property - メンバ名:FirstName

値 : 礼司

メンバ型:Property - メンバ名:LastName

値 : 安部

メンバ型:Property - メンバ名:Birthday

値 : 1971/10/10 0:00:00

メンバ型:Property - メンバ名:FamilyNames

値 : 安部優, 安部永太, ちび安部

メンバ型:Property - メンバ名:CarName

値 : GT-R

メンバ型:Property - メンバ名:Engine

値 : VR38DETT

メンバ型:Property - メンバ名:DryWeight

値 : 1740

メンバ型:Property - メンバ名:HorsePower

値 : 480

--------------汎用的な出力の仕方(List版)--------------

メンバ型:Property - メンバ名:FirstName

値 : 礼司

メンバ型:Property - メンバ名:LastName

値 : 安部

メンバ型:Property - メンバ名:Birthday

値 : 1971/10/10 0:00:00

メンバ型:Property - メンバ名:FamilyNames

値 : 安部優, 安部永太, ちび安部

メンバ型:Property - メンバ名:FirstName

値 : aaa

メンバ型:Property - メンバ名:LastName

値 : bbb

メンバ型:Property - メンバ名:Birthday

値 : 1971/10/10 0:00:00

メンバ型:Property - メンバ名:FamilyNames

メンバ型:Property - メンバ名:FirstName

値 : ccc

メンバ型:Property - メンバ名:LastName

値 : sss

メンバ型:Property - メンバ名:Birthday

値 : 1971/10/10 0:00:00

メンバ型:Property - メンバ名:FamilyNames

プロジェクト内で扱うクラスの数が多くて、クラス内メンバの値が一気にほしい時などはこのようにリフレクションを使ってやると便利ですね。

参考:

dobon.net:型(クラス、構造体など)のすべてのメンバを取得する オブジェクトからメンバの型情報を取得する方法について解説されています。

dobon.net:型のメンバを動的に呼び出す オブジェクトのメンバの値を取得する方法です。今回はページ中ほどの「MethodInfo、ConstructorInfo、PropertyInfo、FieldInfoクラスを使用した方法」を使っています。