LoginSignup
5
16

More than 5 years have passed since last update.

[.NET] リフレクション スニペット集

Last updated at Posted at 2019-01-16

よく使いそうなリフレクションのスニペットを集めてみました。
※型を明示するため、var はあえて使用していません(一部除く)。
※安全性と処理速度を考慮し、利用は必要最低限に絞りましょう。

インスタンス生成

public/引数なし

Sample sample = Activator.CreateInstance<Sample>();

public/引数あり

object[] args = new object[] { true };
Sample sample = (Sample)Activator.CreateInstance(typeof(Sample), args);

非 public/引数あり

object[] args = new object[] { 1 };
Sample sample = (Sample)Activator.CreateInstance(typeof(Sample), BindingFlags.NonPublic | BindingFlags.Instance, null, args, null);

フィールドアクセス

非 public/インスタンスフィールド

※静的フィールドの場合、BindingFlags.Instance → BindingFlags.Static

Sample sample = new Sample();
FieldInfo field = sample.GetType().GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(sample, true);
bool fieldValue = (bool)field.GetValue(sample);

プロパティアクセス

非public/インスタンスプロパティ

※静的フィールドの場合、BindingFlags.Instance → BindingFlags.Static

Sample sample = new Sample();
PropertyInfo property = sample.GetType().GetProperty("PrivateProperty", BindingFlags.NonPublic | BindingFlags.Instance);
property.SetValue(sample, true, null);
bool propertyValue = (bool)property.GetValue(sample, null);

メソッド呼び出し

非 public/インスタンスメソッド

Sample sample = new Sample();
MethodInfo method = sample.GetType().GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
object[] args = new object[] { 1 };
bool returnValue = (bool)method.Invoke(sample, args);

ref 引数

// 引数を false から true に変える ChangeByRefToTrue メソッドを呼び出す。
Sample sample = new Sample();
Type[] paramTypes = new Type[] { typeof(bool).MakeByRefType() };
MethodInfo method = sample.GetType().GetMethod("ChangeByRefToTrue", BindingFlags.NonPublic | BindingFlags.Instance, null, paramTypes, null);
bool inValue = false;
object[] args = new object[] { inValue };
method.Invoke(sample, args);
bool outValue = (bool)args[0];

Assert.IsFalse(inValue);
Assert.IsTrue(outValue);

属性情報

SampleAttribute attribute = (SampleAttribute)Attribute.GetCustomAttribute(typeof(Sample), typeof(SampleAttribute));
bool attributeProperty = attribute.Foo;

アセンブリ情報

現在実行中のコードを格納しているアセンブリ

Assembly executingAssembly = Assembly.GetExecutingAssembly();

現在実行中のメソッドを呼び出したメソッドのアセンブリ

Assembly callingAssembly = Assembly.GetCallingAssembly();

実行可能ファイルのアセンブリ

※アンマネージアプリケーションから読み込まれている場合、null

Assembly entryAssembly = Assembly.GetEntryAssembly();

実行可能ファイルのパス

string exePath = Application.ExecutablePath;

型情報

型判定

Type type = typeof(Sample);
// 列挙型か。
bool isEnum = type.IsEnum;
// 値型か。
bool isValueType = type.IsValueType;
// Nullを許可する値型か。
bool isNullableValueType = (Nullable.GetUnderlyingType(type) != null);

型名

Assert.AreEqual("String", typeof(String).Name);

型名(コンパイル時解決)

※C# 6.0 / VB 2015~ ならリフレクションよりまずこちらを検討

Assert.AreEqual("String", nameof(String));

メソッド情報

現在のメソッド名

string currentMethodName = MethodBase.GetCurrentMethod().Name;

呼び出し元のメソッド名

※コンパイラによってインライン展開されていないことが前提です。
※.NET 4.5~ は、CallerMemberNameAttribute を使用して引数から取得できます。

StackFrame frame = new StackFrame(1);
string callerMethodName = frame.GetMethod().Name;

メソッド名(コンパイル時解決)

※C# 6.0 / VB 2015~ ならリフレクションよりまずこちらを検討

Assert.AreEqual("IndexOf", nameof(String.IndexOf));

プロパティ情報

現在のプロパティ名

public bool Property
{
    get
    {
        MethodBase accessor = MethodBase.GetCurrentMethod();
        string propertyName = GetProperty(accessor).Name;
        return true;
    }
}

アクセサからプロパティ情報を取得するメソッド

public static PropertyInfo GetProperty(MethodBase accessor)
{
    PropertyInfo[] properties = accessor.DeclaringType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
    foreach (PropertyInfo property in properties)
    {
        MethodInfo[] methods = property.GetAccessors(true);
        foreach (MethodInfo method in methods)
        {
            if (method == accessor)
            {
                return property;
            }
        }
    }
    return null;
}

Lambda 式からプロパティ名を取得するメソッド

public static string GetPropertyName<TObject, TProperty>(Expression<Func<TObject, TProperty>> getter)
{
    var lambda = (LambdaExpression)getter;
    var memberExpression = lambda.Body as MemberExpression;

    if (memberExpression == null)
    {
        // TProperty が object の場合、ボックス化によって UnaryExpression となる。
        var body = (UnaryExpression)lambda.Body;
        memberExpression = (MemberExpression)body.Operand;
    }

    return memberExpression.Member.Name;
}

// 使用例
string propertyName = GetPropertyName((Sample s) => s.PublicProperty);

プロパティ名(コンパイル時解決)

※C# 6.0 / VB 2015~ ならリフレクションよりまずこちらを検討

Assert.AreEqual("Length", nameof(String.Length));
5
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
16