現在 α 版としてですが、インテリセンスにある程度対応した状態にて WF Designer Express をアップさせてもらっています。インテリセンス自体もまだまだ改良中ですが、その際に表示するツールチップヒントの文字列生成というのが、なかなかよく分かっていなかったのでまとめてみました。
メソッドの情報自体は MethodInfo クラスにて参照できるようになっています。MethodInfo クラス自体は Type.GetMethods などで抽出する事が可能です。そして抽出した MethodInfo クラスのプロパティを色々見る事で、ヒント用の文字列(Public Sub New とか、Private Function Test(ByVal a As String) As String とか)を生成する事が可能です。
1: Private Function CreateMethodDescription(ByVal target As MethodInfo) As String
2: Dim desc As New Text.StringBuilder
3: If target.IsPublic Then desc.Append("Public ")
4: If target.IsFamily Then desc.Append("Protected ")
5: If target.IsAssembly Then desc.Append("Friend ")
6: If target.IsPrivate Then desc.Append("Private ")
7: If target.IsAbstract Then desc.Append("MustOverride ")
8: If target.IsVirtual AndAlso Not target.IsFinal Then desc.Append("Overridable ")
9: If target.IsStatic Then desc.Append("Shared ")
10:
11: If (Not target.ReturnType Is GetType(Void)) Then
12: desc.Append("Function ")
13: Else
14: desc.Append("Sub ")
15: End If
16:
17: desc.Append(target.Name)
18: desc.Append(CreateGenericParameter(target))
19:
20: desc.Append("(")
21: Dim paramIndex As Integer = 0
22: For Each param In target.GetParameters
23: If paramIndex > 0 Then desc.Append(", ")
24: If param.IsOptional Then desc.Append("Optional ")
25: If param.IsOut Then
26: desc.Append("ByRef ")
27: Else
28: desc.Append("ByVal ")
29: End If
30: desc.Append(param.Name + " As " + param.ParameterType.Name)
31: desc.Append(CreateGenericParameter(param.ParameterType))
32: If Not IsDBNull(param.DefaultValue) Then
33: If param.DefaultValue Is Nothing Then
34: desc.Append(" = Nothing")
35: Else
36: desc.Append(" = " + param.DefaultValue.ToString)
37: End If
38: End If
39: paramIndex += 1
40: Next
41: desc.Append(") ")
42: If target.ReturnType IsNot Nothing Then
43: desc.Append("As " + target.ReturnType.Name)
44: desc.Append(CreateGenericParameter(target.ReturnType))
45: End If
46: Return desc.ToString
47: End Function
48:
49: Private Overloads Function CreateGenericParameter(ByVal target As MethodInfo) As String
50: Dim result As New Text.StringBuilder
51: If target.IsGenericMethod Then
52: result.Append("(Of ")
53: Dim genIndex As Integer = 0
54: For Each genParam In target.GetGenericArguments
55: If genIndex > 0 Then result.Append(", ")
56: result.Append(genParam.Name)
57: genIndex += 1
58: Next
59: result.Append(")")
60: End If
61: Return result.ToString
62: End Function
一気にロジックを掲載しますが、基本力技でやりましたw
まずメソッドが Public なのか Private なのかについてを前半部分にて行っています。ここでは Public、Protected、Friend、Private、MustInherits、Overridable、Shared については判別できますが、Overloads については判別できません。力技でやるとすると該当するクラスのメソッド情報をみて同名のメソッドがあるかどうか、で行うのだと思います。
続いて行っているのは、Sub か Function かの判定です。VB 使いとしては短絡的に
「値を返さない=ReturnType が Nothing」
のようにすぐ思ってしまったのですが、値を返さない=Void ですよね……。
ジェネリックについては後述するとして、渡される引数についての判定として GetParameters メソッドで取得した引数情報を元にループ処理を行います。ここでは VB 使いならではの点があり(最近の C# では記述できるけど)Optional と ByRef、そして Default の判断も行っています。少しひっかかったのは Default でして、初期値=Nothing、という記述は普通にできる事をすっかり失念していました。なお初期値がない場合は、DefaultValue プロパティに DBNull が設定されるという、少々特殊な状況になりますので気を付けてください。
後回しにしたジェネリックですが、別メソッドに切り分けてある部分が該当します。今回は MethodInfo からの処理について記載していますが、実際にはもう一つ Type からの処理版も作成しています。違いはジェネリックかどうかを判断する部分の聞き方だけで、MethodInfo の場合は IsGenericMethod プロパティにて、Type から行う場合は IsGenericType プロパティにて判断する必要があります。判断後は全く一緒です。
このような処理を行う事で、インテリセンスで利用するヒント文字列を作成する事ができます。
0 件のコメント:
コメントを投稿