リフレクションを利用すると、動的に型のインスタンスを作成したり、メソッドやプロパティにアクセスできるようになります。
具体例を見た方が話しが速いです。
PropertyInfo[] myPropertyInfo = hoge.GetType().GetProperties(BindingFlags.Instance|BindingFlags.Public);
foreach (var property in myPropertyInfo)
{
var val1 = property.GetValue(hoge);
var val2 = property.GetValue(fuga);
if (!Equals(val1, val2))
{
property.SetValue(hoge, property.GetValue(fuga));
}
}
変数hogeに対してGetType()を行い、型を取得します。例えばClass Hogeとか。
型が分かっている場合は、typeof(Hoge)でもいいですね。
で、この型に対して、GetProperties()を行うことでプロパティをすべて取得できます。
必要に応じて、インスタンスのPublicなものだけ欲しい場合は上のようにしますし、
フィールドが欲しい時などは()内の条件を書き換えてあげます。
プロパティ名を取得できれば、プロパティ名.GetValue(object)でオブジェクトのプロパティの値が取得できます。
値を入れるには、SetValue(object, value)を使います。
GetValue
冒頭の例では異なるインスタンスであるhogeとfugaの値が同じでなければ代入するというような処理になります。
Reflectionそのものとは関係がないですが、GetValueはobjectが返る仕様のため、val1 == val2とした場合、参照の比較となってしまい、値が等しい場合でもfalseになります(∵boxing 値型から参照型への変換)。そのためEqualsで比較します。
public object GetValue (object obj);
PropertyInfo.GetValue メソッド (System.Reflection)
指定されたオブジェクトのプロパティの値を返します。
BindingFlags
GetPropertiesでプロパティを取得する場合に条件を指定できます。
この時、publicなプロパティだけを取得する場合、クラス変数なのかインスタンス変数なのかを区別するため、BindingFlags.PublicのみならずBindingFlags.Instanceも指定しなければなりません。
.GetProperties(BindingFlags.Instance | BindingFlags.Public);
これを設定しない場合、GetPropertiesを行ってもNullが返ります。
コメント