Reflection(C# WPF)

C#

リフレクションを利用すると、動的に型のインスタンスを作成したり、メソッドやプロパティにアクセスできるようになります。

具体例を見た方が話しが速いです。

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)
指定されたオブジェクトのプロパティ値を返します。Returns the property value of a specified object.

BindingFlags

GetPropertiesでプロパティを取得する場合に条件を指定できます。
この時、publicなプロパティだけを取得する場合、クラス変数なのかインスタンス変数なのかを区別するため、BindingFlags.PublicのみならずBindingFlags.Instanceも指定しなければなりません。

.GetProperties(BindingFlags.Instance | BindingFlags.Public);

これを設定しない場合、GetPropertiesを行ってもNullが返ります。

コメント