作成日: 2015/12/24, 更新日: 2015/12/24
リフレクションを使って、各メンバーの詳細情報を取得しよう
- リフレクションについての第2回目です。 フィールド、プロパティ、メソッド等の各メンバーへのアクセス方法と操作方法を記載しています。
- 第1回目はこちらです。
メンバー別の取得方法を知ろう
- 前回は、リフレクションについてさらっと機能別に紹介しました。 動的実行するにしろ、メンバー情報を取得するにしろ、取得メソッド、設定メソッドを通して、処理を操作していくという特徴があります。 今回は、メンバー別の取得方法について、より詳しく説明したいと思います。
スポンサーリンク
インスタンスメンバーを取得する
- それではサンプルからです。ちょっと長いです。
- 【解析側】取得メソッド
Imports System.Reflection Private Sub ShowMemberInfo(t As Type) Dim b As BindingFlags = BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.Static Or BindingFlags.DeclaredOnly For Each member In t.GetMembers(b) Select Case True Case TypeOf member Is FieldInfo Me.ShowFieldInfo(member) Case TypeOf member Is PropertyInfo Me.ShowPropertyInfo(member) Case TypeOf member Is MethodInfo Me.ShowMethodInfo(member) End Select Next End Sub Private Sub ShowFieldInfo(member As MemberInfo) Dim accessModifier As String = String.Empty Dim info As FieldInfo = CType(member, FieldInfo) Select Case True Case info.IsFamilyOrAssembly : accessModifier = "Protected Friend" Case info.IsPrivate : accessModifier = "Private" Case info.IsFamily : accessModifier = "Protected" Case info.IsAssembly : accessModifier = "Friend" Case info.IsPublic : accessModifier = "Public" End Select Console.WriteLine("kind = {0}, name = {1} : type = {2}, accessModifier = {3}", info.MemberType, info.Name, info.FieldType, accessModifier) End Sub Private Sub ShowPropertyInfo(member As MemberInfo) Dim accessModifier As String = String.Empty Dim info As PropertyInfo = CType(member, PropertyInfo) accessModifier = Me.GetAccessModifier(info) Console.WriteLine("kind = {0}, name = {1} : type = {2}, accessModifier = {3}", info.MemberType, info.Name, info.PropertyType, accessModifier) End Sub Private Sub ShowMethodInfo(member As MemberInfo) Dim accessModifier As String = String.Empty Dim info As MethodInfo = CType(member, MethodInfo) Select Case True Case info.IsFamilyOrAssembly : accessModifier = "Protected Friend" Case info.IsPrivate : accessModifier = "Private" Case info.IsFamily : accessModifier = "Protected" Case info.IsAssembly : accessModifier = "Friend" Case info.IsPublic : accessModifier = "Public" End Select Console.WriteLine("kind = {0}, name = {1} : type = {2}, accessModifier = {3}", info.MemberType, info.Name, info.ReturnType, accessModifier) End Sub Private Enum AccessModifiers None [Private] [Protected] [Friend] [Protected_Friend] [Public] End Enum Private Function GetAccessModifier(p As PropertyInfo) As String ' プロパティのアクセスレベルの判断は、 ' ゲッター/セッターそれぞれのアクセス修飾子のうち、ゆるい方がプロパティのアクセス修飾子である、という判断をします。 ' (StackOverflow の記事から) Dim readAccess As String = "None" Dim writeAccess As String = "None" If p.CanRead Then readAccess = Me.GetAccessModifierCore(p.GetMethod()) If p.CanWrite Then writeAccess = Me.GetAccessModifierCore(p.SetMethod()) ' 微調整 If readAccess = "Protected Friend" Then readAccess = "Protected_Friend" If writeAccess = "Protected Friend" Then writeAccess = "Protected_Friend" ' いったん数値に変換して、大小比較 Dim readModifier As AccessModifiers = AccessModifiers.None Dim writeModifier As AccessModifiers = AccessModifiers.None [Enum].TryParse(readAccess, readModifier) [Enum].TryParse(writeAccess, readModifier) ' 微調整戻しをして、返却 If readModifier < writeModifier Then Return writeAccess.Replace("Protected_Friend", "Protected Friend") Else Return readAccess.Replace("Protected_Friend", "Protected Friend") End If End Function Private Function GetAccessModifierCore(m As MethodInfo) As String Dim x As String = String.Empty Select Case True Case m.IsFamilyOrAssembly : x = "Protected Friend" Case m.IsPrivate : x = "Private" Case m.IsFamily : x = "Protected" Case m.IsAssembly : x = "Friend" Case m.IsPublic : x = "Public" End Select Return x End Function
' チェック対象のクラス Public Class Person Private _Age As Integer = -1 Public Property Age As Integer Get Return _Age End Get Set(value As Integer) _Age = value End Set End Property Public Sub ShowMessage(msg As String) Console.WriteLine(msg) End Sub Public Function Plus(i1 As Integer, i2 As Integer) As Integer Return i1 + i2 End Function End Class
' 情報を取得します。(ロードイベントやボタンのクリックイベントなどに貼り付けてください) Dim t As Type = GetType(Person) Me.ShowMemberInfo(t)
' 出力結果 kind = Method, name = get_Age : type = System.Int32, accessModifier = Public kind = Method, name = set_Age : type = System.Void, accessModifier = Public kind = Method, name = ShowMessage : type = System.Void, accessModifier = Public kind = Method, name = Plus : type = System.Int32, accessModifier = Public kind = Property, name = Age : type = System.Int32, accessModifier = Public kind = Field, name = _Age : type = System.Int32, accessModifier = Private
スポンサーリンク
共有メンバーを取得する
- 続いては、共有メンバーを取得してみます。
- 【呼び出し側】の処理
' チェック対象のクラス Public Class Person2 Private Shared _Age As Integer = -1 Protected Friend Shared Property Age As Integer Get Return _Age End Get Private Set(value As Integer) _Age = value End Set End Property Protected Shared Sub ShowMessage(msg As String) Console.WriteLine(msg) End Sub Friend Shared Function Plus(i1 As Integer, i2 As Integer) As Integer Return i1 + i2 End Function End Class
' 情報を取得します。(ロードイベントやボタンのクリックイベントなどに貼り付けてください) Dim t2 As Type = GetType(Person2) Me.ShowMemberInfo(t2)
' 出力結果 kind = Method, name = get_Age : type = System.Int32, accessModifier = Protected Friend kind = Method, name = set_Age : type = System.Void, accessModifier = Private kind = Method, name = ShowMessage : type = System.Void, accessModifier = Protected kind = Method, name = Plus : type = System.Int32, accessModifier = Friend kind = Property, name = Age : type = System.Int32, accessModifier = Protected Friend kind = Field, name = _Age : type = System.Int32, accessModifier = Private
イベント、コンストラクタ、メソッドの引数メンバーを取得する
- 続いて、イベント、メソッドの引数に関する情報です。
- 【解析側】取得メソッド
Imports System.Reflection Private Sub ShowMemberInfo(t As Type) Dim b As BindingFlags = BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.Static Or BindingFlags.DeclaredOnly For Each member In t.GetMembers(b) Select Case True Case TypeOf member Is ConstructorInfo Me.ShowConstructorInfo(member) Case TypeOf member Is MethodInfo Me.ShowMethodInfo(member) Dim m As MethodInfo = CType(member, MethodInfo) If 0 < m.GetParameters.Count Then For Each p In m.GetParameters Me.ShowParameterInfo(p) Next End If Case TypeOf member Is EventInfo Me.ShowEventInfo(member) End Select Next End Sub Private Sub ShowConstructorInfo(member As MemberInfo) Dim accessModifier As String = String.Empty Dim info As ConstructorInfo = CType(member, ConstructorInfo) Select Case True Case info.IsFamilyOrAssembly : accessModifier = "Protected Friend" Case info.IsPrivate : accessModifier = "Private" Case info.IsFamily : accessModifier = "Protected" Case info.IsAssembly : accessModifier = "Friend" Case info.IsPublic : accessModifier = "Public" End Select Console.WriteLine("kind = {0}, name = {1} : type = {2}, accessModifier = {3}", info.MemberType, info.Name, "System.Void", accessModifier) End Sub Private Sub ShowMethodInfo(member As MemberInfo) Dim accessModifier As String = String.Empty Dim info As MethodInfo = CType(member, MethodInfo) Select Case True Case info.IsFamilyOrAssembly : accessModifier = "Protected Friend" Case info.IsPrivate : accessModifier = "Private" Case info.IsFamily : accessModifier = "Protected" Case info.IsAssembly : accessModifier = "Friend" Case info.IsPublic : accessModifier = "Public" End Select Console.WriteLine("kind = {0}, name = {1} : type = {2}, accessModifier = {3}", info.MemberType, info.Name, info.ReturnType, accessModifier) End Sub Private Sub ShowParameterInfo(p As ParameterInfo) Dim byvalOrByRef As String = "ByVal" If p.ParameterType.IsByRef Then byvalOrByRef = "ByRef" Console.WriteLine(vbTab & "number = {0}, argument passing = {1}, name = {2} : type = {3}", p.Position, byvalOrByRef, p.Name, p.ParameterType) End Sub Private Sub ShowEventInfo(member As MemberInfo) Dim accessModifier As String = String.Empty Dim info As EventInfo = CType(member, EventInfo) Console.WriteLine("kind = {0}, name = {1}", info.MemberType, info.Name) End Sub
' チェック対象のクラス Public Class Person3 Public Event PersonalClick(sender As Object, e As EventArgs) Public Sub OnMyClick() RaiseEvent PersonalClick(Me, New EventArgs) End Sub Public Function Plus(i1 As Integer, i2 As Integer) As Integer Return i1 + i2 End Function End Class
' 情報を取得します。(ロードイベントやボタンのクリックイベントなどに貼り付けてください) Dim t3 As Type = GetType(Person3) Me.ShowMemberInfo(t3)
' 出力結果 kind = Method, name = __ENCAddToList : type = System.Void, accessModifier = Private number = 0, argument passing = ByVal, name = value : type = System.Object kind = Method, name = add_PersonalClick : type = System.Void, accessModifier = Public number = 0, argument passing = ByVal, name = obj : type = WindowsApplication353.Person3+PersonalClickEventHandler kind = Method, name = remove_PersonalClick : type = System.Void, accessModifier = Public number = 0, argument passing = ByVal, name = obj : type = WindowsApplication353.Person3+PersonalClickEventHandler kind = Method, name = OnMyClick : type = System.Void, accessModifier = Public kind = Method, name = Plus : type = System.Int32, accessModifier = Public number = 0, argument passing = ByVal, name = i1 : type = System.Int32 number = 1, argument passing = ByVal, name = i2 : type = System.Int32 kind = Constructor, name = .cctor : type = System.Void, accessModifier = Private kind = Constructor, name = .ctor : type = System.Void, accessModifier = Public kind = Event, name = PersonalClick
Dim t As Type = GetType(Form5) Me.ShowMemberInfo(t)
' 出力結果 (省略)
' 出力結果 ~省略~ kind = Method, name = Form5_Load : type = System.Void, accessModifier = Private number = 0, argument passing = ByVal, name = sender : type = System.Object number = 1, argument passing = ByVal, name = e : type = System.EventArgs ~省略~
' 出力結果 ~省略~ kind = Event, name = AutoSizeChanged kind = Event, name = AutoValidateChanged kind = Event, name = HelpButtonClicked kind = Event, name = MaximizedBoundsChanged kind = Event, name = MaximumSizeChanged kind = Event, name = MarginChanged ~省略~
まとめ
- このように、リフレクションを使うと、プログラムの中からいろいろな情報を取得することができるようになります。 プラグイン操作の材料として、または、自分が作ったプログラムの特性を分析して(具体的にはアイディア次第ですが)、 さらなる技術力の向上につながれば幸いです。
- 最後までこの記事を読んでいただき、ありがとうございました。
スポンサーリンク