ラムダ式を使用して、コンパイル時のプロパティ参照を解決できます。(ラムダ式からのプロパティ名の取得から変更されたコード)
public PropertyInfo GetPropertyInfo<TProperty>(
Expression<Func<TProperty>> propertyLambda)
{
MemberExpression member = propertyLambda.Body as MemberExpression;
if (member == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a method, not a property.",
propertyLambda.ToString()));
PropertyInfo propInfo = member.Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a field, not a property.",
propertyLambda.ToString()));
return propInfo;
}
拡張メソッドとして使用する必要はありません (ただし、適応させたい場合は使用できますが、ソース オブジェクト インスタンスは、行を記述する以外は必要ありません)。
public class Test
{
public string Prop { get; set; }
}
Test t = new Test();
PropertyInfo propInfo = GetPropertyInfo(() => t.Prop);
Console.WriteLine(propInfo.Name + " -> " + propInfo.PropertyType); //Prop -> System.String
編集: 適切な構文が必要で、その型のオブジェクトへの既存の参照を避ける必要がある場合は、次のようにすることができます。
public static class TypedReflection<TSource>
{
public static PropertyInfo GetPropertyInfo<TProperty>(
Expression<Func<TSource, TProperty>> propertyLambda)
{
MemberExpression member = propertyLambda.Body as MemberExpression;
if (member == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a method, not a property.",
propertyLambda.ToString()));
PropertyInfo propInfo = member.Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a field, not a property.",
propertyLambda.ToString()));
return propInfo;
}
}
そして、次のように呼び出します。
PropertyInfo propInfo = TypedReflection<Test>.GetPropertyInfo(o => o.Prop);
この時点で、型指定されたリフレクション メソッド (get メソッド、フィールドなど) を追加するのは非常に簡単です。
EDIT:それはまだ2つのジェネリック型に依存していますが、型推論によって隠されています。私は 2 番目の例を好みます。最低限、宣言するクラスの型を指定する必要がありますが (型の安全性が必要なため)、オブジェクト インスタンスは必要ありません。また、プロパティの名前を変更すると、このコードに伝播され、PropertyInfo
.