はかせのラボ

私の頭の中を書いていく雑記ブログです

C# BindingFlagsについて調べてみた話

あいさつ

どうも、はかせです。
前回デストラクタの取得で結構詰まってしまいました。

原因はBindingFlagsの設定がミスってたからなんですが、
そも論そこに指定するBindingFlagsについて私はほとんど知りません。

今までの奴もほぼ全てネットのコピペです。

まぁ大体定型文なんでそこまで神経質に
ならなくてもいいのかもしれませんが、
前回は知らなくて詰まってしまったので
ちゃんと調べたいと思いました。

今回はそのメモ的な記事になります。

BindingFlagsとは

リファレンスより

バインドおよびリフレクションによるメンバーと型の検索方法を制御するフラグを指定します
引用:BindingFlags Enum (System.Reflection) | Microsoft Docs

GetMethodとかでクラスの中身をリフレクションで
探すときにどういう探し方をするか定義できるものらしいです。

とりあえず私が過去に使ったことのあるものを
上げていきましょう。

・Public
・NonPublic
・InvokeMethod
・Instance

意外と少なかった・・・・

ま、まぁそれぞれ見てきましょう。

Public

Publicメンバーを探します。
そのまんまですね。

GetMethodは名前のみで検索をかけると
内部的にPublic、Instance、Staticの三つを指定して
検索しているようです。

NonPublic

非Publicメンバーを探します。

私が前回詰まったデストラクタも非Publicメソッドだったので
この指定が必要でした。

InvokeMethod

これは今までのものと少し毛色が違って
探したメソッドを呼び出すことを指定します。

本来非Publicメソッドは外部から触れることが
できないため呼び出すこともできません。

ただこのフラグを指定すると
呼び出すことができるようになるそうです。

明示的に呼ぶということを示すことに
意味があるのかもしれませんね。

Instance

インスタンスメンバーを検索に含めます。

要はインスタンスメソッド探すってことだと思います。
非PublicでもStaticだったりすることがあるので
その差別化だと思います。

つまり前回のデストラクタの探し方は

デストラクタ検索には
NonPublic、InvokeMethod、Instanceの三つを指定しました。

これ直訳すると
「非Publicのインスタンスメソッドを探して呼び出す」って感じですかね。

そしてこれ書いてて思ったのが
「あれ?これってもしかしてPrivate触れるんじゃね?」

試してみましょう。

まずはこんな感じでPrivate持つクラス作って

public class A
{
    private void HelloWorld()
    {
        Console.WriteLine("Hello World");
    }
}

んでこんな感じで探してみる。

var method = typeof(A).GetMethod("Hello World", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod);
Console.WriteLine(method == null ? "Null" : method.Name);

答えは?
f:id:hakase0274:20190924194216p:plain

悲しい(´;ω;`)
やっぱPrivateにおさわりできるのは
DynamicMethodだけなんですね。

DynamicMethodについてはこちらをどうぞ
hakase0274.hatenablog.com

あとがき

今回はBindingFlagsについて調べてみました。
基本この記事であげた四つ+Staticであらかた事足りるのかななんて思ってます。

そしてBindingFlagsの力をもってしてもPrivateの壁は破れなかった・・・
改めてDynamicMethodの異常さがわかりました。

それでは今回はこの辺でノシ